不知道之前在哪看的一句话:"在 JS 里, 一切都是对象~", 当时觉得还挺有道理的. 毕竟像常用的函数, 数组等的确都是对象!(可以用 typeof 查看).
补充一句: typeof null // "object"
因为这个是 JS 一开始的 bug
来谈谈关于 typeof 的原理吧, 我们可以先想一个很有意思的问题, JS 在底层是怎么存储数据的类型信息呢? 或者说, 一个 JS 的变量, 在它的底层实现中, 它的类型信息是怎么实现的呢?
其实, JS 在底层存储变量的时候, 会在变量的机器码的低位 1-3 位存储其类型信息
000: 对象
010: 浮点数
100: 字符串
110: 布尔
1: 整数
but, 对于 undefined 和 null 来说, 这两个值的信息存储是有点特殊的.
null: 所有机器码均为 0
undefined: 用 −2^30 整数来表示
所以, typeof 在判断 null 的时候就出现问题了, 由于 null 的所有机器码均为 0, 因此直接被当做了对象来看待.
真的全是对象吗?
- var a = ''
- b = 1
- c = new String('1')
- d = new Number(1)
- typeof a // 'string'
- typeof b // 'number'
- typeof c // 'object'
- typeof d // 'object'
为什么会出现这种差异呢?
因为 JS 里有 6 中基本类型:
- undefined // typeof undefined 'undefined'
- null // typeof null 'object'
- string //
- number //
- Boolean // typeof true 'boolean'
- Symbol
当我们以字面量的方式创建 string, number 时, 创建出来的属于基本类型, 而通过构造器创造出来时它是一个对象!
但是!~ 竟然字面量创造出来的玩意儿不是对象, 它为什么会有方法和属性!!
- var a = 'a'
- a.toString() // 'a'
- a.length // 1
按道理说属性和方法应该是对象特有的呀!
于是乎, 引出了 JS 的另一个概念, 装箱和拆箱!
JS 里的装箱和拆箱
概念:
1. 装箱指的是, 将一个值变成指向该值的对象.(复制值)
2. 拆箱指的是, 把指向值的对象还原成该值.(复制值)
装箱
- var a = 'str'
- a.toString()
当执行 toString() 方法时, JS 会自动将其包装成 String 对象再调用方法. 过程如下:
- { // 伪代码
- var b = new String(a)
- b.toString()
- b = null
- }
然后我们就看到了正常的输出'a'
这个也可以解释另外一个问题:
- var a='str'
- a.name='test'
- console.log(a.name) // undefined
聪明的你一定可以想到这是为什么了!
拆箱
- var a = new String('str')
- console.log(a) // String {
- "str"
- }
- var b = a + '1'
- console.log(b) // str1
这里就是一个拆箱的过程, JS 做的事情和上面装箱类似.
- var b = a + '1'
- {
- var temp = a.toString() // or valueOf or
- var b = temp + '1'
- }
类型转换时会经常发生装箱和拆箱操作, 需要注意
来源: http://www.jianshu.com/p/78e76e94ddb9