面試總結

walt-white發表於2021-04-25

1.undefined和null的區別

null: Null型別,代表“空值”,代表一個空物件指標,使用typeof運算得到 “object”,所以你可以認為它是一個特殊的物件值。

undefined: Undefined型別,當宣告瞭一個變數而未初始化時,得到的就是undefined,使用typeof運算得到 “undefined”。

2.js基本的資料型別

ECMAScript中有5中簡單資料型別(也稱為基本資料型別): Undefined、Null、Boolean、Number和String。
還有1中複雜的資料型別————Object。Object本質上是由一組無序的名值對組成的。

3.原生獲取元素的方法

JS獲取DOM元素的方法(8種)

通過ID獲取(getElementById)

通過name屬性(getElementsByName)

通過類名class(getElementsByClassName)

通過標籤名(getElementsByTagName)

通過選擇器獲取一個元素(querySelector)

通過選擇器獲取一組元素(querySelectorAll)

獲取html的方法(document.documentElement) 
document.documentElement是專門獲取html這個標籤的

獲取body的方法(document.body) 
document.body是專門獲取body這個標籤的。

4.css選擇器
①.ID選擇器 #
②.類選擇器 .
③.標籤選擇器 p,div,span
④.偽類選擇器 :link :active :visited :hover
⑤.通用選擇器 *
⑥.屬性選擇器 [attr='']
⑦.偽類選擇器 :first-child :nth-child() :first-letter :after :before

5.js中的new關鍵字

一、認識new運算子:

    function Animal(name){                      // 建立Animal建構函式
        this.name = name;
    }
    Animal.color = "black";
    Animal.prototype.say = function(){
        console.log("I'm " + this.name);
    };
    var cat = new Animal("cat");                // 建立cat例項

    console.log(
       cat.name,      //cat
       cat.color      //undefined
    );
    cat.say();        //I'm cat

    console.log(
       Animal.name,   //Animal
       Animal.color   //black
    );
    Animal.say();     //Animal.say is not a function

1、程式碼解讀

1-3行---建立了一個函式Animal,並在其this上定義了屬性:name,name的值是函式被執行時的形參。

第4行---在Animal物件(Animal本身是一個函式物件)上定義了一個靜態屬性:color,並賦值“black”。

5-7行---在Animal函式的原型物件prototype上定義了一個say()方法,say方法輸出了this的name值。

第8行---通過new關鍵字建立了一個新物件cat。

10-14行---cat物件嘗試訪問name和color屬性,並呼叫say方法。

16-20行---Animal物件嘗試訪問name和color屬性,並呼叫say方法。

2、重點解析

第8行程式碼是關鍵:

var cat = new Animal("cat");

JS引擎執行這句程式碼時,在內部做了很多工作,用虛擬碼模擬其工作流程如下:

new Animal("cat") = {
    var obj = {};
    obj.__proto__ = Animal.prototype;
    var result = Animal.call(obj,"cat");
    return typeof result === 'object'?result:obj;
}

程式碼解析:

(1)建立一個空物件obj;

(2)把obj的__ proto__ 指向Animal的原型物件prototype,此時便建立了obj物件的原型鏈:obj->Animal.prototype->Object.prototype->null

如果你不瞭解JS原型鏈,請先閱讀:JS原型和原型鏈

(3)在obj物件的執行環境呼叫Animal函式並傳遞引數“cat”。 相當於var result = obj.Animal("cat")。當這句執行完之後,obj便產生了屬性name並賦值為"cat"。

關於JS中call的用法請閱讀:JS的call和apply

(4)考察第3步返回的返回值,如果無返回值或者返回一個非物件值,則將obj返回作為新物件;否則會將返回值作為新物件返回。

理解new的執行機制以後,我們知道cat其實就是過程(4)的返回值,因此我們對cat物件的認知就多了一些:

16301110-c6f3eca57958b0c9.png
image.png
cat.__ proto__ == Animal.prototype
Animal.prototype.__ proto__ == Object.prototype
Object.prototype.__ proto__ == null

__ proto__和prototype 以下三點需要謹記:

1.每個物件都具有一個名為__ proto__的屬性;

2.每個建構函式(建構函式標準為大寫開頭,如Function(),Object()等等JS中自帶的建構函式,以及自己建立的)都具有一個名為prototype的方法(注意:既然是方法,那麼就是一個物件(JS中函式同樣是物件),所以prototype同樣帶有__ proto__屬性);

3.每個物件的__ proto__屬性指向自身建構函式的prototype;

所以cat的原型鏈是:

cat->Animal.prototype->Object.prototype->null

cat上新增了一個屬性:name屬性。

所以此時cat物件為:


16301110-5a5409edc71273c8.png
image.png

★:例項物件(cat)的 __ proto __ == 建構函式(Animal)的prototype。
即:cat.__ proto __ == Animal.prototype
(注:#proto前後無空格,若不輸入空格,在此無法顯示__,故在此加上前後空格)

★:例項物件(cat)的constructor == 建構函式(Animal)。
即:cat.constructor == Animal


16301110-184d0ebad5bf0e6a.png
image.png

分析完了cat的產生過程,我們再看看輸出結果:

cat.name -> 在過程(3)中,obj物件就產生了name屬性。因此cat.name就是這裡的obj.name

cat.color -> cat會先查詢自身的color,沒有找到便會沿著原型鏈查詢,在上述例子中,我們僅在Animal物件上定義了color,並沒有在其原型鏈上定義,因此找不到。

cat.say -> cat會先查詢自身的say方法,沒有找到便會沿著原型鏈查詢,在上述例子中,我們在Animal的prototype上定義了say,因此在原型鏈上找到了say方法。

另外,在say方法中還訪問this.name,這裡的this指的是其呼叫者obj,因此輸出的是obj.name的值。

對於Animal來說,它本身也是一個物件,因此,它在訪問屬性和方法時也遵守上述查詢規則,所以:

Animal.color -> "black"

Animal.name -> "Animal" , Animal先查詢自身的name,找到了name,注意:但這個name不是我們定義的name,而是函式物件內建的屬性。

一般情況下,函式物件在產生時會內建name屬性並將函式名作為賦值(僅函式物件)。

Animal.say -> Animal在自身沒有找到say方法,也會沿著其原型鏈查詢,話說Animal的原型鏈是什麼呢?

16301110-8f6746c32ef1e07d.png
image.png
Animal.__ proto __ == Function.prototype
Function.prototype.__ proto__ == Object.prototype
Object.prototype.__ proto__ == null

所以Animal的原型鏈是:

Animal->Function.prototype->Object.prototype->null

二、new存在的意義

認識了new運算子之後,我們再回到開篇提到的問題:JS中萬物皆物件,為什麼還要通過new來產生物件?要弄明白這個問題,我們首先要搞清楚cat和Animal的關係。

通過上面的分析,我們發現cat繼承了Animal中的部分屬性,因此我們可以簡單的理解:Animal和cat是繼承關係。

我們用這個方法來判斷一下cat和Animal

cat instanceof Animal; //true

從執行結果看:cat確實是Animal例項物件,要想證實這個結果,我們再來了解一下JS中instanceof的判斷規則:

var L = cat.__ proto __;
var R = B.prototype;
if(L === R) return true;

如果A的__ proto __ 等價於 B的prototype,就返回true。

在new的執行過程(2)中,cat的proto指向了Animal的prototype,所以cat和Animal符合instanceof的判斷結果。因此,我們認為:cat是Animal的例項物件。

簡單的總結語

在javascript中, 通過new可以產生原物件的一個例項物件,而這個例項物件繼承了原物件的屬性和方法。因此,new存在的意義在於它實現了javascript中的繼承,而不僅僅是例項化了一個物件!

6.GET和POST請求方式的區別

GET和POST是HTTP請求的兩種基本方法。

最直觀的區別就是GET把引數包含在URL中,POST通過request body傳遞引數。

①.GET請求只能進行url編碼,而POST支援多種編碼方式。

②.GET請求引數會被完整保留在瀏覽器歷史記錄裡,而POST中的引數不會被保留。

③.GET請求在URL中傳送的引數是有長度限制的,而POST沒有。

④.對引數的資料型別,GET只接受ASCII字元,而POST沒有限制。

⑤.POST比GET更安全,因為GET引數直接暴露在URL上,所以不能用來傳遞敏感資訊。

⑥.GET引數通過URL傳遞,POST放在Request body中。

7.rem.js

適配移動端的Rem.js:

window.onload = function(){
    /*750代表設計師給的設計稿的寬度,你的設計稿是多少,就寫多少;100代表換算比例,這裡寫100是
      為了以後好算,比如,你測量的一個寬度是100px,就可以寫為1rem,以及1px=0.01rem等等*/
    getRem(750,100)
};
window.onresize = function(){
    getRem(750,100)
};
function getRem(pwidth,prem){
    var html = document.getElementsByTagName("html")[0];
    var oWidth = document.body.clientWidth || document.documentElement.clientWidth;
    html.style.fontSize = oWidth/pwidth*prem + "px";
}

8.陣列去重:

①.第一種方法

var arr=[1,2,3,4,5,6,7,6,5,4,3];
var newArr=[];
for(var i=0; i<arr.length; i++){
    if(arr.indexOf(arr[i])==i){
        newArr.push(arr[i])
    }
}
console.log(newArr);

②第二種方法

var arr=[1,2,3,4,5,6,7,6,5,4,3];
var newArr=[];
for(var i=0; i<arr.length; i++){
    if(newArr.indexOf(arr[i])==-1){
        newArr.push(arr[i])
    }
}
console.log(newArr);

③第三種方法

var arr=[1,2,3,4,5,6,7,6,5,4,3];
function quchong(arr){
    var res = [arr[0]]
    for(var i=1; i<arr.length; i++){
        var repeat = false;
        for(var j=0; j<res.length; j++){
            if(arr[i] == res[j]){
                repeat = true;
                break;
            }
        }
        if(!repeat){
            res.push(arr[i]);
        }
    }
    console.log(res);
}
quchong(arr)

9.駝峰命名法

var str='get-element-by-id';
function join(str){
    var arr=str.split('-');
    var newStr='';
    for(var i=0;i<arr.length;i++){
        if(i==0){
            newStr+=arr[i]
        }else{
            newStr+=arr[i].slice(0,1).toUpperCase()+arr[i].slice(1);
        }
    }
    console.log(newStr);
}
join(str);

10.垂直水平居中

#box {
    background-color: #FF8C00;
    width: 300px;
    height: 300px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-left: -50px;
    margin-top: -50px;
}
.inner {
    background-color: #F00;
    display: inline-block;
    width: 100px;
    height: 100px;
}

#box {
    background-color: #FF8C00;
    width: 300px;
    height: 300px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50px,-50px);
}
.inner {
    background-color: #F00;
    display: inline-block;
    width: 100px;
    height: 100px;
}

#box {
    background-color: #FF8C00;
    width: 300px;
    height: 300px;
            
    /*flex*/
    display: flex;
    justify-content: center;
    align-items: center;
}
.inner {
    background-color: #F00;
    display: inline-block;
    width: 100px;
    height: 100px;
}

#box {
    background-color: #FF8C00;
    width: 300px;
    height: 300px;
    /*table-cell*/
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
.inner {
    background-color: #F00;
    display: inline-block;
    width: 100px;
    height: 100px;
}

相關文章