JavaScript的基本类型Symbol

 

  • 数据类型 “symbol” 是一种原始数据类型
  • Symbol 本质上是一种唯一标识符,可用作对象的唯一属性名,这样其他人就不会改写或覆盖你设置的属性值。
  • Symbol() 函数会返回symbol类型的值,该类型具有静态属性和静态方法。
  • 作为构造函数来说它并不完整,因为它不支持语法:"new Symbol()"。
  • 每个从Symbol()返回的symbol值都是唯一的。
  • 一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的。

声明方法:

let name = Symbol("fx");
typeof name; // 'symbol'
console.log(name) // Symbol(fx)

Symbol 数据类型的特点是唯一性,即使是用同一个变量生成的值也不相等。

let id1 = Symbol('id');
let id2 = Symbol('id');
console.log(id1 == id2);  //false

symbol 不可强制转换

var fxNames = Symbol("fx");
fxNames + '213' // Uncaught TypeError: Cannot convert a Symbol value to a string

// 如果真的相加,可以先String(fxNames)之后再相加

Symbol 数据类型的另一特点是隐藏性,for···in,object.keys() 不能访问

let id = Symbol('id')
let obj = {
    [id]: 'symbol'
}
for (let option in obj) {
    console.log(obj[option]) // 空
}

但是也有能够访问的方法:Object.getOwnPropertySymbols
Object.getOwnPropertySymbols 方法会返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。

let id = Symbol('id')
let obj = {
    [id]: 'symbol'
}
let array = Object.getOwnPropertySymbols(obj)
console.log(array) // [Symbol(id)]
console.log(obj[array[0]])  // 'symbol'

虽然这样保证了Symbol的唯一性,但我们不排除希望能够多次使用同一个symbol值的情况。
为此,官方提供了全局注册并登记的方法:Symbol.for()

let name1 = Symbol.for('name') // 检测到未创建后新建
let name2 = Symbol.for('name') // 检测到已创建后返回
console.log(name1 === name2) // true

通过这种方法就可以通过参数值获取到全局的symbol对象了,反之,能不能通过symbol对象获取到参数值呢?
是可以的 ,通过Symbol.keyFor()

let name1 = Symbol.for('name');
let name2 = Symbol.for('name');
console.log(Symbol.keyFor(name1));  // 'name'
console.log(Symbol.keyFor(name2)) // 'name'

Symbol.hasInstance用于判断某对象是否为某构造器的实例。因此你可以用它自定义 instanceof 操作符在某个类上的行为。

实现一个自定义的instanceof 行为,例如:

class MyArray {  
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}
console.log([] instanceof MyArray); // true

Symbol.isConcatSpreadable符号用于配置某对象作为Array.prototype.concat()方法的参数时是否展开其数组元素。

默认情况下,Array.prototype.concat() 展开其元素连接到结果中:

var alpha = ['a', 'b', 'c'], 
    numeric = [1, 2, 3]; 

var alphaNumeric = alpha.concat(numeric); 

console.log(alphaNumeric); // 结果: ['a', 'b', 'c', 1, 2, 3]

设置Symbol.isConcatSpreadablefalse

var alpha = ['a', 'b', 'c'], 
    numeric = [1, 2, 3]; 

numeric[Symbol.isConcatSpreadable] = false;
var alphaNumeric = alpha.concat(numeric); 

console.log(alphaNumeric); // 结果: ['a', 'b', 'c', [1, 2, 3] ]

对于类数组 (array-like)对象,默认不展开。期望展开其元素用于连接,需要设置 Symbol.isConcatSpreadable 为true:

var x = [1, 2, 3];

var fakeArray = { 
  [Symbol.isConcatSpreadable]: true, 
  length: 2, 
  0: "hello", 
  1: "world" 
}

x.concat(fakeArray); // [1, 2, 3, "hello", "world"]

Symbol.toPrimitive 是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。

  • 在 Symbol.toPrimitive 属性(用作函数值)的帮助下,一个对象可被转换为原始值。
  • 该函数被调用时,会被传递一个字符串参数 hint ,表示要转换到的原始值的预期类型。 
  • hint 参数的取值是 "number""string" 和 "default" 中的任意一个。
  • // 一个没有提供 Symbol.toPrimitive 属性的对象,参与运算时的输出结果
    var obj1 = {};
    console.log(+obj1);     // NaN
    console.log(`${obj1}`); // "[object Object]"
    console.log(obj1 + ""); // "[object Object]"
    
    // 接下面声明一个对象,手动赋予了 Symbol.toPrimitive 属性,再来查看输出结果
    var obj2 = {
      [Symbol.toPrimitive](hint) {
        if (hint == "number") {
          return 10;
        }
        if (hint == "string") {
          return "hello";
        }
        return true;
      }
    };
    console.log(+obj2);     // 10      -- hint 参数值是 "number"
    console.log(`${obj2}`); // "hello" -- hint 参数值是 "string"
    console.log(obj2 + ""); // "true"  -- hint 参数值是 "default"

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wflynn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值