- 数据类型 “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"