型別—-《你不知道的js》

圓滾滾的程式猿發表於2019-01-15

一、內建型別

js共有7種內建型別:

  • 空值(null)
  • 未定義(undefined)
  • 布林值(boolean)
  • 數字(number)
  • 字串(string)
  • 物件(object)
  • 符號(symbol, ES6新增)

除物件外,其他統稱為“基本型別”

我們可用typeof來檢視值的型別:

typeof undefined === "undefined";
// truetypeof true === "boolean";
// truetypeof 42 === "number";
// truetypeof "42" === "string";
// truetypeof {
life: 42
} === "object";
// true// ES6新增型別typeof Symbol() === "symbol";
// true複製程式碼

null比較特殊,typeof對它處理有問題:

typeof null === "object";
// true複製程式碼

正確結果應該返回null,但這個bug由來已久,在js中已經存在了將近20年,由於牽涉到太多的Web系統,“修復”它會產生更多的bug,令許多系統無法修復。

我們需要使用符合條件來檢測null的型別:

var a = null;
(!a &
&
typeof a === "object");
// true複製程式碼

null是假值,也是唯一一個用typeof檢測會返回“object”的基本型別

還有一種情況:

typeof function a() { 
/*...*/
} === "function";
// true複製程式碼

function也是js的一個內建函式。實際上是object的一個“子型別”。具體來說,函式是“可呼叫物件”,它有一個內部屬性[[Call]],該屬性使其可以被呼叫。

函式不僅是物件,還可以擁有屬性。如:

function a(b, c) { 
/*..*/
}複製程式碼

函式物件的length屬性是其宣告的引數的個數:

a.length;
// 2複製程式碼

該函式宣告瞭兩個命名引數,b、c,所以其length值為2

typeof [1, 2, 3] === "object";
// true複製程式碼

陣列也是物件,確切的說是object的一個“子型別”,陣列的元素按數字順序來進行索引,其length屬性是元素的個數

三、值和型別

js中的變數是沒有型別的,只有值才有。變數可以隨時持有任何型別的值。js不做“型別強制”,語言引擎不要求變數總是持有與其初始值同型別的值。

在對變數執行操作時,得到的結果並不是該變數的型別,而是該變數持有的值的型別,因為js中的變數沒有型別

var a = 42;
typeof a;
// "number"a = true;
typeof a;
// "boolean"複製程式碼

typeof運算子總是會返回一個字串:

typeof typeof 42;
// "string"複製程式碼

typeof 42 = “number”, typeof “number” = “string”

1、undefined和undeclared

變數在未持有值的時候為undefined,此時typeof返回“undefined”

var a;
typeof a;
// "undefined"var b = 42;
var c;
b = c;
typeof b;
// "undefined"typeof c;
// "undefined"複製程式碼

大多數開發者傾向於undefined等同於undeclared(未宣告),但在js中他們完全是兩回事

  • undefined:已在作用域中宣告但還沒有賦值的變數
  • undeclared:還沒有在作用域中宣告過的變數
var a;
a;
// undefinedb;
// ReferenceError: b is not defined複製程式碼

undefined 和 is not defined是兩碼事。若此時瀏覽器報錯成“b is not found” 或 “b is not declared”會更準確

var a;
typeof a;
// "undefined"typeof b;
// "undefined"複製程式碼

對於undeclared變數,typeof照樣返回”undefined”

雖然b是一個undeclared變數,但typeof b沒報錯,這是因為typeof有一個特殊的安全防範機制

2、typeof Undeclared

該安全防範機制對在瀏覽器中執行的js程式碼很有幫助,因為多個指令碼檔案會在共享的全域性名稱空間中載入變數。

如何在程式中檢查全域性變數DEBUG才不會出現RefrenceError錯誤,這是typeof的安全防範機制就能做到:

// 這樣會報錯if (DEBUG) { 
console.log("Debugging is staring");

}// 這樣是安全的if (typeof DEBUG !== "undefined") {
console.log("Debugging is staring");

}複製程式碼

還有一種不通過typeof的安全防範機制的方法,就是檢查所有全域性變數是否是全域性物件的屬性,瀏覽器中的全域性物件是window

if (window.DEBUG) { 
// ..
}if (!window.atob) {
// ..
}複製程式碼

與undeclared變數不同,訪問不存在的物件屬性(甚至是在全域性物件window上)不會產生RefrenceError錯誤。

來源:https://juejin.im/post/5c3d3e0be51d453ba810104b

相關文章