• 数据类型 “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.isConcatSpreadable​​​为​​false​​:

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"