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