如何在 ES6 中使用 Symbol 对象
随着 ES6 的推出,JavaScript 引入了一种新的原始数据类型 Symbol。Symbol 是一种原始数据类型,使用 Symbol() 函数可以创建一个唯一的值,这个值可以用作对象的属性名,从而可以避免属性名的冲突问题。
Symbol 的主要特点是唯一性,也就是说每个 Symbol 值都是唯一的,即便是创建了相同名称的 Symbol 值也不同。同时,它不会自动转换为字符串,因此不会与其它属性名冲突。
在 ES6 中,Symbol 提供了一种新的方式去创建对象的私有属性,这意味着私有属性只能在对象内部被访问,而外部无法访问,避免了命名空间污染的问题。
接下来,本文将为大家详细介绍如何在 ES6 中使用 Symbol 对象。
使用 Symbol() 函数创建一个 Symbol 值
我们可以使用 Symbol() 函数创建一个唯一的 Symbol 值,如下所示:
const mySymbol = Symbol();
上面的代码创建了一个唯一的 Symbol 值 mySymbol。
使用 Symbol() 函数时可以传递一个参数,该参数是可选的,用于给 Symbol 值添加一个描述,例如:
const mySymbol = Symbol("mySymbol");使用 Symbol 作为对象的属性名
Symbol 可以作为对象的属性名,如下所示:
const mySymbol = Symbol("mySymbol");
const myObj = {};
myObj[mySymbol] = "hello world";
console.log(myObj[mySymbol]); // "hello world"在上面的代码中,我们创建了一个 Symbol 值 mySymbol,并将其作为对象 myObj 的属性名。属性值为 "hello world"。可以发现,在使用 Symbol 值作为属性名时,必须使用方括号 [] 访问该属性。
在对象字面量语法中使用 Symbol 作为属性名,可以使用中括号 [] 或者使用计算属性名的方式进行赋值,例如:
const mySymbol = Symbol("mySymbol");
const myObj = {
[mySymbol]: "hello world"
};
console.log(myObj[mySymbol]); // "hello world"使用 Symbol 作为私有属性
Symbol 作为私有属性的应用是比较常见的。在 ES6 中,我们可以使用 Symbol 作为私有属性,如下所示:
// www.javascriptcn.com code example
// 创建一个私有方法
const mySymbol = Symbol("mySymbol");
class MyClass {
[mySymbol]() {
console.log("this is a private method");
}
publicMethod() {
this[mySymbol]();
}
}
const myObj = new MyClass();
myObj.publicMethod(); // 输出 "this is a private method"
myObj[mySymbol](); // TypeError: myObj[mySymbol] is not a function在上面的代码中,我们使用了 Symbol 作为私有方法 mySymbol 的名称。我们使用方括号 [] 定义私有方法,并在类的公共方法中调用私有方法。
需要注意的是,在使用 Symbol 作为私有属性时,我们并不能完全避免其被其它方式所访问。因为使用 Symbol 创建的属性本质上还是一个对象属性,因此仍然可以通过 Reflect.ownKeys() 或 Object.getOwnPropertySymbols() 方法获取到这些属性。
使用 Symbol.iterator 创建迭代器
Symbol.iterator 是一个内置的 Symbol 值,当我们在一个对象上使用 for...of 循环时,会调用 Symbol.iterator 方法,从而返回一个迭代器对象。
例如,我们可以使用 Symbol.iterator 创建一个可以迭代的对象,如下所示:
// www.javascriptcn.com code example
const mySymbol = Symbol("mySymbol");
const myObj = {
[mySymbol]: [1, 2, 3, 4],
[Symbol.iterator]() {
let index = 0;
const values = this[mySymbol];
return {
next: function() {
if (index < values.length) {
return { value: values[index++], done: false };
} else {
return { done: true };
}
}
}
}
};
for (const item of myObj) {
console.log(item); // 1 2 3 4
}在上面的代码中,我们使用 Symbol.iterator 创建了一个迭代器对象。并将该迭代器对象返回给 myObj,从而可以使用 for...of 循环遍历 myObj 中的数据。
使用 Symbol.hasInstance 创建 instanceof 操作符的行为
Symbol.hasInstance 方法是一个内置的 Symbol 值,当我们在对象上使用 instanceof 操作符时,会调用该方法,从而返回一个布尔值,表示是否为该对象的实例。
例如,我们可以使用 Symbol.hasInstance 创建一个可以匹配对象类型的函数,如下所示:
// www.javascriptcn.com code example
const mySymbol = Symbol("mySymbol");
class MyClass {
static [mySymbol](instance) {
return instance instanceof Array;
}
}
console.log([] instanceof MyClass); // false
console.log([] instanceof MyClass[mySymbol]); // true在上面的代码中,我们使用 Symbol.hasInstance 创建了一个可以匹配数组类型的函数。在使用 instanceof 实例对象和 MyClass 进行对比时,返回 false,而在使用 instanceof 实例对象和 MyClass[mySymbol] 进行对比时,返回 true。
jsbin 示例:https://jsbin.com/xecudac/edit?js,console
综上所述,Symbol 是 ES6 新增的一个原始数据类型,它的主要特点是唯一性。在 ES6 中,我们可以使用 Symbol 创建私有属性、迭代器对象、匹配对象类型的函数等。对于前端开发者来说,熟练掌握 Symbol 对象是非常有必要的。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d00b26e46428fe9ec8ef99