Javascript数据类型
值类型和引用类型
- 原始类型(alias: 值类型,基础类型) primitive:
stringnumberbooleanundefinedsymbolnull - 引用类型:
Object其他内置Object派送类型ArrayFunctionMapSetWeakMapWeakSetRegExp - NaN: 特殊的
Number类型,IsNaN()判断一个值是否为NaN
值类型引用类型存在的差异
- 引用类型可以有属性和方法,而基础值类型是不可以的
- 为什么
'text'.length可以访问到'text'的length属性?→ 包装类
- 为什么
- 引用类型在堆上, 值类型在栈上
- 引用类型值可变,基础值类型值不可变
- 值类型是按值比较的,引用类型比较的是引用的地址
包装类
String Number Boolean Symbol
new String('') 和 String('') 的区别
new String('')构造一个String实例, 得到的是一个对象;let a = new String('a'); let b = new String('b'),a和b是不相等的,ab保存的是两个不同的引用地址- 直接调用
String函数的话是会执行类型转换,这个函数返回的就是一个值类型的string;String(1)返回值是'1'
'text'.length 能够工作的原因
通过 .(术语:属性访问器Property Accessor) 访问值类型 'text' 的 length 属性时, 会发生类型转换(装箱),值类型的 'text' 会转换为引用类型的 String 实例(相当与 new String('text')), 然后这个 String 实例的 length 属性会被返回;
每次访问一个 string 值类型的属性时,都会 new 一个新的 String 包装类,返回这个包装类实例对应的属性值,返回后这个包装类的实例就会立即被丢弃
Number Boolean 同理, Symbol 比较特殊, new Symbol 会抛出 TypeError, 详见下文 → Symbol
值类型转换为引用类型(ToObject)的逻辑 → TC39 - sec-toobject

Symbol
Symbol 是一个比较特殊的包装类, 因为无法通过 new 操作符创建 Symbol 实例
通常直接通过 Symbol('bar') 函数创建值类型的 symbol
Symbol(key: string) 不论传入的参数 key 是什么,都会保证返回唯一的 symbol 值类型, 也就是通过 Symbol(key: string) 函数创建的每个 symbol 都是不相等的
let s = Symbol('foo');
let b = Symbol('foo');
console.log(s === b); // false
Symbol.for
Symbol.for(key: string) 可以保证返回相同的 symbol 类型, 如果传入的参数 key 已在全局 symbol 仓库中, 那么返回那个仓库中对应 key 的 symbol, 否则创建一个新的 symbol
Symbol.keyFor
Symbol.keyFor(s: symbol) 接受一个 symbol 作为参数,返回参数 s:symbol 的 key, s: symbol 必须是通过 Symbol.for(key: string) 创建在全局 symbol 仓库中的才行,否则会返回 undefined
let s = Symbol.for('foo');
console.log(Symbol.keyFor(s)); // 'foo'
Symbol的使用场景
- 用作对象属性的键值(
key), 可以有效防止对象属性的键值冲突;- 这应该是最主要的用途了,解决属性名称冲突问题,mdn和其他一些资料都提到了这个
- Symbol 是 es6 中引入的, 引入 Symbol 的动机应该是为了解决私有属性的问题; 但是实际上并没有
Object.getOwnPropertySymbols(object: Object)返回参数object的所有symbol属性数组- 设置可以通过内置的通用Symbol访问对象的某些属性
Javascript中通用Symbol(well-known Symbols)
Symbol 的静态属性中包含的通用Symbol 如下
- Symbol.iterator with Iterable and Iterator protocol
- Symbol.search
- Symbol.toStringTag
- Symbol.unscopables
- Symbol.isConcatSpreadable
- Symbol.toPrimitive
- Symbol.prototype
- Symbol.split
- Symbol.hasInstance
- Symbol.match
- Symbol.species
类型检测
typeof 和 instanceof
typeof 检测基础值类型
console.log(typeof '1') // string
console.log(typeof 1) // number
console.log(typeof false) // boolean
console.log(typeof Symbol('foo')) // symbol
console.log(typeof undefined) // undefined
console.log(typeof null) // object
console.log(typeof new Date()) // object
有一个特例 typeof null 的返回值按理说应该是 null 但实际却是 object; 这其实是一个bug
简单来说,
typeof null的结果为Object的原因是一个bug。在javascript的最初版本中,使用的32位系统,js为了性能优化,使用低位来存储变量的类型信息。
在判断数据类型时,是根据机器码低位标识来判断的,而null的机器码标识为全0,而对象的机器码低位标识为000。所以typeof null的结果被误判为Object。
instanceof 检测引用类型,判断指定值原型是否在原型链上的任意一个类型
console.log(new Date() instanceof Date) // true
参考资料
简书 - 【JS】string和String差异详解,基本类型和包装类学习
MDN - Symbol
MDN中文- Symbol
掘金 - JavaScript进阶知识点
Github - everything-you-need-to-know-about-javascript-symbols
为什么typeof null的结果是Object?

浙公网安备 33010602011771号