Symbol是JavaScript的一种基本数据类型,是ES6新增的一种数据类型。Symbol是用于防止属性名冲突而产生的,比如向第三方对象中添加属性时,可以通过Symbol函数创建Symbol类型的值,Symbol的值是唯一的,独一无二的不会重复的,即使创建相同参数的Symbol,它们也是不相等的。
Symbol的主要特点和用法:
唯一性:每个通过Symbol()函数创建的Symbol值都是唯一的,即使创建时传入相同的参数,它们也不相等。这意味着Symbol可以用来创建独一无二的属性名,避免属性名冲突的问题。
const symbol1 = Symbol();
const symbol2 = Symbol();
console.log(symbol1); //symbol
console.log(symbol1 === symbol2); // 输出 false
Symbol 属性:可以使用Symbol值作为对象的属性名来定义属性,这样可以确保属性不会被意外覆盖,但是需要注意的是,Symbol不可以添加属性,他本身是一种原始数据类型,它的属性是不可写的,也就是说无法像普通对象那样直接给Symbol类型的变量添加属性。当你尝试给Symbol类型的变量添加属性时,实际上并没有给这个Symbol对象添加属性,而是在尝试给全局对象中创建一个新的属性。
//错误使用
let hd = Symbol();
hd.name = "小王";
console.log(hd.name);//undefined
//正确用法
const mySymbol = Symbol();
const obj = {
[mySymbol]: 'value'
};
console.log(obj[mySymbol]); // 输出 'value'
隐藏属性:由于Symbol属性在 for...in 循环、Object.keys()、JSON.stringify() 等方法中是不可枚举的,所以可以利用Symbol属性来定义隐藏的、不被意外访问到的私有属性。
const hiddenProperty = Symbol('hidden');
const obj = {
visibleProperty: 'public',
[hiddenProperty]: 'private'
};
console.log(obj.visibleProperty); // 输出 'public'
console.log(obj[hiddenProperty]); // 输出 'private'
for (let key in obj) {
console.log(key); // 输出 'visibleProperty',但不会输出 'hidden'
}
console.log(Object.keys(obj)); // 输出 ['visibleProperty']
可以使用 Object.getOwnPropertySymbols 获取所有Symbol属性,Object.getOwnPropertySymbols() 方法会返回所有直接在对象上定义的Symbol属性,无论是否可枚举。它不返回其他类型的属性名(如字符串属性名)。如果需要获取所有属性名,包括字符串和Symbol属性,可以使用Object.getOwnPropertyNames()方法。
for (const key of Object.getOwnPropertySymbols(obj)) {
console.log(key);//Symbol(hidden)
}
也可以使用 Reflect.ownKeys() 方法。 Reflect.ownKeys(obj) 方法会获取所有属性包括Symbol。
for (const key of Reflect.ownKeys(obj)) {
console.log(key);//visibleProperty Symbol(hidden)
}
Symbol.for() 和 Symbol.keyFor() :Symbol.for()方法可以根据描述获取Symbol,如果不存在则创建一个全局共享的Symbol,而Symbol.keyFor()方法可以返回一个已经登记的Symbol的键,找不到则返回undefined。
const globalSymbol = Symbol.for('global');
const globalSymbol2 = Symbol.for('global');
console.log(globalSymbol == globalSymbol2); //true
console.log(Symbol.keyFor(globalSymbol)); // 输出 'global'
const test = Symbol("test");
console.log(Symbol.keyFor(test)); //undefined
Symbol类型的引入使JavaScript在属性命名和属性保护方面更加灵活和安全。它提供了一种机制来确保属性名的唯一性,并且可以隐藏对象的属性。