读完《你不知道的JavaScript中卷》

160 阅读2分钟

类型和语法

类型

js是弱类型语言,也是动态语言

JavaScript有七种内置类型

  • 空值(null)
  • 未定义(undefined)
  • 布尔值(boolean)
  • 数字(number)
  • 字符串(string)
  • 对象(object)
  • 符号(symbol,ES6中新增)

除对象之外,其他统称为“基本类型”

可以用typeof运算符查看值的类型,它返回的是类型的字符串值,typeof的安全防范机制(组织报错)来检查undeclared变量

typeof undefined === 'undefined'
typeof true === 'boolean'
typeof 42 === 'number'
typeof '42' === 'string'
typeof { life: 42 } === 'object'
typeof Symbol() === 'symbol'
typeof (() => {}) === 'function'
typeof [] === 'object'

正确的返回结果应该是"null",但这个bug由来已久,在JavaScript中已经存在了将近20年

typeof null === 'object'

判断null值的类型

var a = null;
(!a && typeof a === 'object')
Object.prototype.toString.call(null) // "[object Null]"

特殊等式

ES6中新加入了一个工具方法Object.is()来判断2个值是否绝对相等

var a = 2 / 'foo'
var b = -3 * 0

Object.is(a, NaN) // true
Object.is(b, -0) // true

Object.is(b, 0) // false

值和引用

简单值(即标量基本类型值)总是通过值复制的方式来赋值/传递,包括null、undifined、字符串、数字、布尔、symbol

复合值---对象(包括数组、和封装对象)和函数,总是通过引用复制的方式来赋值/传递

function foo(x) {
  x.push(4)
  x = [4, 5, 6]
  x.push(7)
  x
}

var a = [1, 2, 3]
foo(a)
a // [1, 2, 3, 4]

我们向函数传递a的时候,实际是将引用a的一个复本赋值给x,而a仍然指向[1, 2, 3],在函数中我们可以通过引用x来更改数组的值(push(4)之后变为[1, 2, 3, 4])。但x = [4, 5, 6]并不影响a的指向,所以a仍然指向[1, 2, 3, 4]

原生函数

常用的原生函数有:

String()
Number()
Boolean()
Array()
Object()
Function()
RegExp()
Date()
Error()
Symbol()

内部属性[[Class]]

所有typeof返回值为'object'的对象(如数组)都包含一个内部属性[[Class]](我们可以把它看作是一个内部的分类),而非传统的面相对象意义上的类,这个属性无法直接访问,一般通过Object.prototype.toString()来查看

Object.prototype.toString.call([1, 2, 3]) // "[object Array]"

强制类型转换

隐式强制类型转换

1 + '1'

显式强制类型转换

String(1)
Boolean(1)

JSON字符串化

JSON.stringify不能处理循环引用的json,可以用来判断链表中有没有环

真值假值

假值:

undefined
null
false
+0、 -0NaN
var a = 'Hello World'
if (~a.indexOf('lo')) // 不用判断与-1比较了,直接返回真值和假值
[] + {} // 'object Object'
{} + [] // 0

异步和性能

个人感觉翻译的不太好,重复的东西很多

迭代器

for of循环可以使用的范围

  • 数组
  • Set
  • Map类数组对象,如arguments对象、DOM NodeList对象 Generator对象

而生成器函数内部也有迭代器

可参考

生成器函数自动执行(可以使用TJ大神开发的co模块)