JavaScript數據結構常見面試問題整理

1.JS有哪些數據類型有什麼區別

答:JS共有八大數據類型,分別是:String、Number、Boolean、Object、Null、Undefined、Symbol、BigInt。其中Symbol(獨一無二不可變)和BigInt(任意精度的數字)是ES6中新加入的數據類型。這些數據類型可以分為原始數據類型(String、Number、Boolean、Null、Undefined)和引用數據類型(Object、數組、函數等)。

**區別:**存儲位置不同 原始數據類型直接存儲在棧(stack)中的簡單數據段,占據空間、大小固定,屬於被頻繁使用的數據,所以放在棧中存儲;引用數據類型存儲在堆中的對象,占據空間大、大小不固定,如果存儲在棧中,將會影響程序運行的性能。

  • 在數據結構中,棧中數據的存取方式為先進後出。
  • 堆是一個優先隊列,是按優先級來進行排序的,優先級可以按照大小來規定。

2.數據類型檢測的方式

答:JavaScript有4種方法判斷變量的類型,分別是typeof、instanceof、Object.prototype.toString.call()(對象原型鏈判斷方法)、 constructor (用於引用數據類型) 。typeof:常用於判斷基本數據類型,對於引用數據類型除瞭function返回’function‘,其餘全部返回’object’。 instanceof:主要用於區分引用數據類型,檢測方法是檢測的類型在當前實例的原型鏈上,用其檢測出來的結果都是true,不太適合用於簡單數據類型的檢測,檢測過程繁瑣且對於簡單數據類型檢測不出來。 constructor:用於檢測所有數據類型,檢測方法是獲取實例的構造函數判斷和某個類是否相同,如果相同就說明該數據是符合那個數據類型的,這種方法不會把原型鏈上的其他類也加入進來,避免瞭原型鏈的幹擾。 Object.prototype.toString.call():適用於所有類型的判斷檢測,檢測方法是Object.prototype.toString.call(數據) 返回的是該數據類型的字符串。 這四種判斷數據類型的方法中,各種數據類型都能檢測且檢測精準的就是Object.prototype.toString.call()這種方法。

加分回答 instanceof的實現原理:驗證當前類的原型prototype是否會出現在實例的原型鏈__proto__上,隻要在它的原型鏈上,則結果都為true。因此,instanceof 在查找的過程中會遍歷左邊變量的原型鏈,直到找到右邊變量的 prototype,找到返回true,未找到返回false。 Object.prototype.toString.call()原理:Object.prototype.toString 表示一個返回對象類型的字符串,call()方法可以改變this的指向,那麼把Object.prototype.toString()方法指向不同的數據類型上面,返回不同的結果

(1)typeof:返回數據的類型,但是數組、null、對象、函數,都隻能返回object,所以typeof並不能區分出處理function的其他object中的幾種不同類型。

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof []);              // object    
console.log(typeof function(){});    // function
console.log(typeof {});              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object

衍生問題:為什麼typeof null 是obect ?

原因是:在JS的第一個版本中,所有值都存儲在32位的單元中,每個單元包含一個小的類型標簽,以及當前要存儲的真實數據,類型標簽包括000(object)、1(int)、010(double)、100(string)、110(boolean)。而null的機器碼全是0,所以被認為是object。

(2)instanceof:可以判斷instanceof後面的類型是否正確,返回true / false,內部的運行機制是看能不能在原型鏈中找到該類型的原型。但是instanceof隻能判斷出引用數據類型,並且可以區分出數組、函數等,卻不能判斷基本數據類型。

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true

(3)constructor可以判斷數據類型,還可以訪問對象的構造函數。constructor可以把object分開來判斷。分為(Array、Function、object)

console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true

(4)Object.prototype.toString.call():使用Object對象的原型方法toString來判斷數據類型

var a = Object.prototype.toString;
console.log(a.call(2));  //[object Number]
console.log(a.call(true)); //[object Boolean]
console.log(a.call('str')); //[object String]
console.log(a.call([])); //[object Array]
console.log(a.call(function(){})); //[object Function]
console.log(a.call({})); //[object Object]
console.log(a.call(undefined)); //[object Undefined]
console.log(a.call(null)); //[object Null]

3.判斷是否是數組的方法

var b = new Array();
console.log(b instanceof Array); //true
console.log(Object.prototype.toString.call(b)); //[object Array]
console.log(Array.isArray(b)); //true
console.log(b.constructor===Array); //true
console.log(b.__proto__===Array.prototype); //true
console.log(Array.prototype.isPrototypeOf(b)); //true

4.null和undefined的區別

答:undefind 是全局對象的一個屬性,當一個變量沒有被賦值或者一個函數沒有返回值或者某個對象不存在某個屬性卻去訪問或者函數定義瞭形參但沒有傳遞實參,這時候都是undefined。undefined通過typeof判斷類型是’undefined’。undefined == undefined undefined === undefined 。 null代表對象的值未設置,相當於一個對象沒有設置指針地址就是null。null通過typeof判斷類型是’object’。null === null null == null null == undefined null !== undefined undefined 表示一個變量初始狀態值,而 null 則表示一個變量被人為的設置為空對象,而不是原始狀態。在實際使用過程中,不需要對一個變量顯式的賦值 undefined,當需要釋放一個對象時,直接賦值為 null 即可。 讓一個變量為null,直接給該變量賦值為null即可。typeof null是object。

undefined == null   //true
undefined === null  //false
undefined !== null  //true

5.手寫instanceof方法

function myInstanceof(left,right){
    let proto = Object.getPrototypeOf(left)
    let prototype = right.prototype;
    while(true){
        if(!proto) return false
        if(proto === prototype) return true
        proto = Object.getPrototypeOf(proto)
    }
}
console.log(myInstanceof("",Array)); //false
console.log(myInstanceof([1,2,3],Array)); //true

6.為什麼0.1+0.2 !==0.3

答:首先要知道小數是如何轉為二進制的,整數部分就是不斷除2取餘,小數部分就是乘二取整,超過1以後還是用小數部分乘,如下所示:

//不斷的乘以二然後拿掉整數部分,直到積為0。
//但是結果是不可能為0的,所以是循環的
0.1 * 2 = 0.2 => 0
0.2 * 2 = 0.4 => 0
0.4 * 2 = 0.8 => 0
0.8 * 2 = 1.6 => 1
0.6 * 2 = 1.2 => 1
0.2 * 2 = 0.4 => 0

因此,0.1的二進制是0.0001 1001 1001 1001…無限循環,0.2的二進制是0.0011 0011 0011 0011…無限循環,所以0.3的二進制就是0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100,轉換為十進制就是0.300000004,這就是精度丟失問題,所以0.1+0.2 !== 0.3。可以用toFixed(1)來解決,但也要註意,toFixed()返回的類型是String。

7.isNaN和Number.isNaN函數的區別

  • isNaN接受參數後,會嘗試將這個參數轉換為數值,任何不能轉換的都會返回true,因此,非數字值傳入也會返回true,會影響NaN的判斷。
  • Number.isNaN會首先判斷傳入參數是否是數字,如果是數字再繼續判斷是否為NaN,不會進行數據類型的轉換,更加準確。
console.log(isNaN(NaN)) //true
console.log(isNaN("123")); //false
console.log(isNaN("NaN")); //true
console.log(Number.isNaN(NaN)); //true
console.log(Number.isNaN("123")); //false
console.log(Number.isNaN("NaN")); //false

8.==操作符的強制類型轉換規則

(1)類型相同的話就直接比較;

(2)類型不同的話,會進行類型轉換;

(3)先判斷是不是null 和 undefined,是的話就返回true;

(4)判斷是否是string 和 number,string –> number;

(5)如果有一方是boolean,那麼boolean –> number;

(6)如果一方是object,另一方是string number symbol,把object–> 原始類型。

console.log(NaN == NaN);    //false
console.log(null instanceof Object);   //false 因為null是原型鏈的頂端瞭,而instanceof是根據Object.getPrototypeof()實現的,找不到他的父類瞭
console.log(null == null);  //true
console.log(false == "");   //true
console.log(undefined == false);    //false

9.強制轉換的規則

(1)其他值–>字符串:Null、Undefined、Boolean、Number、Symbol都是直接轉換為字符串,加上雙引號,對於普通對象來說,一般會用toString()轉換為內部屬性[[Class]]的值;

(2)其他值–>數字值:①Undefined類型的值轉換為NaN,Null類型轉換為0,true為1,false為0,String如果包含非數字就為NaN,否則為數字,空字符串為0,Symbol會報錯;

(3)其他值–>佈爾值:false值包括(undefined,null,false,+0,-0,NaN,“”),其他值都是真值。

10.Object.is()與比較操作符===和==的區別

答:==在進行判斷時,如果兩邊類型不一致,會進行轉換,轉換以後再比較;===如果兩邊類型不一致,就不會進行強制類型轉換,直接返回false;Object.is()一般情況下和三等號相同,但是-0和+0不再相等,兩個NaN是相等的。

到此這篇關於JavaScript數據結構常見面試問題整理的文章就介紹到這瞭,更多相關JavaScript數據結構內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: