《你所不知道的JavaScript》-值与类型

变量没有类型,值才有。变量可以随时持有任何类型的值。

所有的值都有一个类型,可能是:

  • Undefined

  • null

  • Number

  • String

  • Boolean

  • Object

  • Symbol

    除对象外,其他统称为基本类型,我们可以使用typeof来获取一个值的类型,但null比较特殊。

    typeof null === 'object' // true
    

    这是一个由来已久的bug,我们需要使用符合条件检测null。

    var a = null;
    (!a && typeof a === 'object'); // true
    

另外一个比较特殊的是函数。

var a = () => {}
typeof a; // function

查阅规范就会知道,function是object的一个“子类型”。具体而言,函数是“可调用对象”,他有一个内部属性[[Call]],该属性使其可以被调用。

null和undefined

Undefined

变量在未持有值的时候为undefined。大多数开发者倾向于将undefined等同于undeclared(未申明),但在JavaScript中完全是两回事情。

已在作用域中声明但还没有赋值的变量是undefined,相反,还没有在作用域中声明过得变量是undeclared。

var a;
a; // undefined
b; // ReferenceError: b is not defined

对UNdeclared的变量执行typeof,会得到undefined,这让人抓狂,因为typeof有一个特殊的安全防范机制。这种处理使得我们比较容易判断当前环境是否已经引入了某一变量。

if(typeof abc === 'undefined') {
    abc = function() {
        // do some thing
    }
}

判断a是否已经在当前环境中,使用typeof a === 'undefined', 而不是 if(a)

Null还是Undefined

  • null指的是空值(empty value)
  • undefined指的是没有值(missing value),从未赋值过

void 0

鉴于在非严格模式下,我们可以为全局标识符undefined赋值。可以看到一些人这样写代码:

var a = void 0 

表达式void没有返回值,它获得一个纯粹的undefined。void并不改变表达式的结果,只是让表达式不返回值。

数组

  1. 在JavaScript中,数组可以容纳任何类型的值
  2. 对数组声明之后即可向其加入值,不需要预设大小。
  3. 使用delete运算符可以将单元从数组中删除,但是单元删除之后,数组的length属性并不会发生变化。
  4. 数据通过数字进行索引,但有趣的是数组也是对象,所以也可以给它添加字符串键值。但这些不计算在数组长度之内。

类数组转换为数组

例如一些DOM查询返回的DOM元素列表,或者函数的arguments对象可以通过以下方法转换为数组:

  • concat()
  • forEach()
  • indexOf()
  • slice()
  • Array.from

字符串

字符串是不可变的,意味着对字符串的操作往往不会直接去修改已有字符串,而是生成新的字符串。

数字

JavaScript只有一种数值类型:number。JavaScript的数字根据IEEE 754标准实现的。

二进制浮点数最大的问题(所有遵循IEEE 754规范的语言),会出现如下情况:

0.1 + 0.2 === 0.3 // false

以上情况的原因在于二进制浮点数中的0.1和0.2并不是十分精确,它们相加的结果比较接近0.300000000000004,所以判断结果是false。

为了解决上面的问题,最常见的方法是设置一个误差范围值,通常为“机器精度(machine epsilon)”, 对于JavaScript的数字而言,这个值通常是 2^-52。从ES6开始这个值定义在 Number.EPSILON中。所以判断小数是否相等可以这样写:

Math.abs(n1 - n2) < Number.EPSILON;

检测一个数字是否是整数,可以使用:

Number.isInteger(33); // true
Number.isInteger(33.00); // true
Number.isInteger(42.3) // false

不是数字的数字

NaN意指“不是一个数字”,将她理解为“无效的数值”可能更准确。例如:

var a = 2 / 'foo';
typeof a === 'number'; // true

NaN是一个“禁戒值”, 用于指出数字类型中的错误情况,即“执行数学运算没有成功”。

检测NaN

NaN是唯一一个不和自身相等的值(非自反, reflexive,即 x === x 不成立)。

  1. 不要使用内建的全局工具函数 isNaN
window.isNaN(NaN) // true
window.isNaN('foo') // true

很明显'foo'不是NaN。

  1. ES6提供了一个工具函数: Number.isNaN().
Number.isNaN(NaN) // true
Number.isNaN('foo') // false
  1. 利用NaN不等于自身这一点,可以使用:

    if(!Number.isNaN) {
        Number.isNaN = n => n !== n;
    }
    

如果你仍在代码里使用window.isNaN, 迟早会出现bug

你可能感兴趣的:(《你所不知道的JavaScript》-值与类型)