《You dont know JS》类型篇总结

类型

javaScript中的类型和熟知的一些强类型语言的有关类型的定义是不一样的。在js中,类型的含义是值的内部特征,它定义了值得行为,以使其区别于其他值。(a type is an intrinsic, built-in set of characteristics that uniquely identifies the behavior of a particular value and distinguishes it from other values)

由此我们就可以看出,js强调的是值的行为,js认为拥有不同行为的值就是不同类型的值,而根据不同行为进行分类,js区分了七种类型:Undefined、Null、Boolean、Number、Object以及ES6新增的Symbol。


一:null和object

typeof null === 'object';   //  true
typeof {} === 'object'; // true

在js中,null被当做object,这是js的一个BUG,修复这个BUG的代价有些大,所以相当时间内不会有什么变化,所以为了准确区分null和object,可以借助取反运算符,如下所示:

!null === true; // true
!{} === false;  // true

var a = null;
if (!a && typeof a === 'object') {  // 为true时,a为null
    ...
}

如上所示,借助这个区别,我们就可以准确区分null和object了。


二:typeof function a() {} === 'function'

如标题所示的结果为true。'function'是object的一个“子类型”。函数是“可调用对象”,它有一个内部属性[[Call]],该属性使其可以被调用。

typeof [1,2,3] === 'object';    // true

同理,数组也是对象,也是object的一个“子类型”。


三:JS中的变量没有类型,值有类型

JS中的变量并不具有类型,所以变量存储的值可以是任意类型且是动态可变的。所以我们说JS是一种“弱类型语言”。

所以,我们在使用typeof检查类型时,检查的并不是变量的类型,而是该变量存储的值的类型。因为JS中的变量没有类型。注意:typeof运算符的返回值总是一个字符串。


四:区分undefined和undeclared

  • undefined:未赋值
  • undeclared:未定义

在js中,undefined表示变量本身已经定义,但是还没有对该变量赋值或者被显示的赋值为undefined。如下所示:

var a;
typeof a;   // 'undefined'
var c = 2;
typeof c;   // 'number'
c = a;
typeof c;   // 'undefined'

与undefined形成鲜明对比的,就是undeclared。如果我们完全还没声明,就直接去调用(注意,这里是直接调用未声明的变量),就会报错,如下所示:

var a;
a;  // 'undefined'
c;  // 'Uncaught ReferenceError: c is not defined'

"c is not defined"并非字面意思表示未定义,这也是为什么要引入一个"undeclared",因为在此处"c is not declared"更准确一些。

但需要注意的一点是,不论是对于已经定义未赋值的变量,还是对于未定义的变量,typeof操作符都会返回"undefined"。

var a;
typeof a;   // undefined
typeof c;   // undefined

会出现上述这种奇怪的现象,是typeof有一个特殊的安全防范机制。这种安全机制还是比较有用的。我觉得大家都写过如下所示的这种代码,但我们需要使用一个变量时,为了避免一些不必要的操作,可能会先对该变量做一个判断:

var name = ''
if (name) { // 如果name的值是空字符串,就不输出
    console.log(name);
}
if (age) {  // 如果age的值是小于等于0的值,就不输出
    console.log(age);
}

现在我们知道,如上所示的代码是存在安全隐患的,我们无法保证name和age都是已经声明过得变量,这就存在安全隐患。这就需要做一个安全验证,这时候typeof的安全机制就有了用处:

var name = '';
if (typeof name !== 'undefined' && name) { // 如果name的值是空字符串,就不输出
    console.log(name);
}
if (typeof age !== 'undefined' && age) {  // 如果obj.age的值是小于等于0的值,就不输出
    console.log(age);
}

同时,typeof操作符还可以验证某个变量当前是否有定义,避免同名覆盖。

if (typeof a === 'undefined') {
    a = {...};
}

当然,如果是访问对象的一个不存在的属性,是不会像访问未声明的变量那样报错的。

var obj = {
    name : 'abc'
}
if (obj.name) { // obj.name => 'abc'
    console.log(obj.name);  // 'abc'
}
if (obj.age) {  // obj.age => 'undefined'
    console.log(obj.age);
}
原文地址:https://www.cnblogs.com/enjoymylift/p/8351415.html