JavaScript 類型及其判斷
JavaScript 具有七種內置數據類型,它們分別是:null、undefined、boolean、number、string、object、symbol,其中object 類型又具體包含了 function、array、date 等
對於這些類型的判斷,我們常用的方法有:typeof、instanceof、Object.prototype.toString、constructor
(一)typeof
使用 typeof 可以准確判斷出除 null 以外的基本類型,以及 function 類型、symbol 類型;null 會被 typeof 判斷為 object。
typeof 5 // "number" typeof 'lucas' // "string" typeof undefined // "undefined" typeof true // "boolean" typeof null // "object" const foo = () => 1 typeof foo // "function" const foo = {} typeof foo // "object" const foo = [] typeof foo // "object" const foo = new Date() typeof foo // "object" const foo = Symbol("foo") typeof foo // "symbol"
(二)instanceof
使用 a instanceof B 判斷的是:a 是否為 B 的實例,即 a 的原型鏈上是否存在 B 構造函數。
function Person(name) { this.name = name } const p = new Person('lucas') p instanceof Person // true
(三) Object.prototype.toString
console.log(Object.prototype.toString.call(1)) // [object Number] console.log(Object.prototype.toString.call('lucas')) // [object String] console.log(Object.prototype.toString.call(undefined)) // [object Undefined] console.log(Object.prototype.toString.call(true)) // [object Boolean] console.log(Object.prototype.toString.call({})) // [object Object] console.log(Object.prototype.toString.call([])) // [object Array] console.log(Object.prototype.toString.call(function(){})) // [object Function] console.log(Object.prototype.toString.call(null)) // [object Null] console.log(Object.prototype.toString.call(Symbol('lucas'))) // [object Symbol]
(四)constructor
var foo = 5 foo.constructor // ƒ Number() { [native code] } var foo = 'Lucas' foo.constructor // ƒ String() { [native code] } var foo = true foo.constructor // ƒ Boolean() { [native code] } var foo = [] foo.constructor // ƒ Array() { [native code] } var foo = {} foo.constructor // ƒ Object() { [native code] } var foo = () => 1 foo.constructor // ƒ Function() { [native code] } var foo = new Date() foo.constructor // ƒ Date() { [native code] } var foo = Symbol("foo") foo.constructor // ƒ Symbol() { [native code] } var foo = undefined foo.constructor // VM257:1 Uncaught TypeError: Cannot read property 'constructor' of undefined at <anonymous>:1:5 var foo = null foo.constructor // VM334:1 Uncaught TypeError: Cannot read property 'constructor' of null at <anonymous>:1:5
對於 undefined 和 null,如果嘗試讀取其 constructor 屬性,將會進行報錯。並且 constructor 返回的是構造函數本身,一般使用它來判斷類型的情況並不多見。
JavaScript 類型及其轉換
JavaScript 是一種弱類型或者說動態語言。這意味着你不用提前聲明變量的類型,在程序運行過程中,類型會被自動確定。
console.log(1 + '1') // 11 console.log(1 + true) // 2 console.log(1 + false) // 1 console.log(1 + undefined) // NaN console.log('lucas' + true) // lucastrue
當使用 + 運算符計算 string 和其他類型相加時,都會轉換為 string 類型;其他情況,都會轉換為 number 類型,但是 undefined 會轉換為 NaN,相加結果也是 NaN
當使用 + 運算符計算時,如果存在復雜類型,那么復雜類型將會轉換為基本類型,再進行運算
對象在轉換基本類型時,會調用該對象上 valueOf 或 toString 這兩個方法,該方法的返回值是轉換為基本類型的結果
JS中Number()、parseInt()和parseFloat()
JavaScript 函數參數傳遞
let foo = 1 const bar = value => { value = 2 console.log(value) } bar(foo) console.log(foo) //2 1 let foo = {bar: 1} const func = obj => { obj.bar = 2 console.log(obj.bar) } func(foo) console.log(foo) //2 {bar: 2}
數為基本類型時,函數體內復制了一份參數值,而不會影響參數實際值。如果函數參數是一個引用類型,當在函數體內修改這個引用類型參數的某個屬性值時,將會對參數進行修改。因為這時候函數體內的引用地址指向了原來的參數。
cannot read property of undefined 問題解決方案
const obj = { user: { posts: [ { title: 'Foo', comments: [ 'Good one!', 'Interesting...' ] }, { title: 'Bar', comments: [ 'Ok' ] }, { title: 'Baz', comments: []} ], comments: [] } }
驗證對象每一個 key 的存在性。常見的處理方案:
&& 短路運算符進行可訪問性嗅探
obj.user && obj.user.posts && obj.user.posts[0] && obj.user.posts[0].comments
|| 單元設置默認保底值
(((obj.user || {}).posts||{})[0]||{}).comments
try…catch
var result try { result = obj.user.posts[0].comments } catch { result = null }
例題:
Can (a == 1 && a == 2 && a == 3) ever evaluate to true?
const a = { value: 1, toString: function () { return a.value++ } } console.log(a == 1 && a == 2 && a == 3) // true let value = 0 Object.defineProperty(window, 'a', { get: function() { return ++value } }) console.log(a == 1 && a == 2 && a == 3) // true