Javascript数据类型

值类型和引用类型

  • 原始类型(alias: 值类型,基础类型) primitive: string number boolean undefined symbol null
  • 引用类型: Object 其他内置Object派送类型 Array Function Map Set WeakMap WeakSet RegExp
  • 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'), ab 是不相等的, a b 保存的是两个不同的引用地址
  • 直接调用 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 仓库中, 那么返回那个仓库中对应 keysymbol, 否则创建一个新的 symbol

Symbol.keyFor

Symbol.keyFor(s: symbol) 接受一个 symbol 作为参数,返回参数 s:symbolkey, 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 如下

  1. Symbol.iterator with Iterable and Iterator protocol
  2. Symbol.search
  3. Symbol.toStringTag
  4. Symbol.unscopables
  5. Symbol.isConcatSpreadable
  6. Symbol.toPrimitive
  7. Symbol.prototype
  8. Symbol.split
  9. Symbol.hasInstance
  10. Symbol.match
  11. Symbol.species

MDN中文- 内置通用Symbol

类型检测

typeofinstanceof

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?

发布平台

博客园
掘金

posted @ 2023-04-23 23:05  Laggage  阅读(42)  评论(0编辑  收藏  举报