浅谈ES6新增类型Symbol

本文介绍了ES6新增的数据类型Symbol的基本概念及其应用场景,包括如何生成Symbol值、Symbol作为对象属性名和函数名的独特作用,以及如何获取对象的Symbol属性。

1Symbol概述

JavaScript基本数据类型有6种:Undefined、Null、Boolean、String、Number、Object。

ES6新增了一种数据类型:Symbol,表示独一无二的值,Symbol最大的用途是用来定义对象的唯一属性名。

ES5的对象属性名都是字符串,容易造成属性名的冲突。如使用了一个其他人提供的对象,但又想为其添加新的方法(mixin模式),那么新方法的名字有可能与已有方法产生冲突。因此,需要保证每个属性的名字都是独一无二,以防止属性名的冲突。这就是ES6引入Symbol的原因。

Symbol值通过Symbol函数生成。

var symbol1 = Symbol();
var symbol2 = Symbol("Alice");
console.log(symbol1, symbol2) // 输出:Symbol() Symbol(Alice)

typeof运算符用于Symbol类型值,返回symbol。

console.log(typeof Symbol("Alice")) // 输出:symbol

Symbol类型的值是一个独一无二的值,Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的。

console.log(Symbol() === Symbol()); // 输出:false
console.log(Symbol("Alice") === Symbol("Alice")); // 输出:false

Symbol不是一个构造函数,如果用new Symbol会报错(Symbol是一个原始类型的值,不是对象)。

var symbol = new Symbol(); // 报错:TypeError

由于Symbol值不是对象,所以不能添加属性。

var symbol = Symbol();
symbol.name = "Alice"; // 报错:TypeError

Symbol值不能与其他类型的值进行运算。

console.log(Symbol('Alice') + "Bruce"); // 报错

Symbol值可以显式转为字符串,也可以转为布尔值,但是不能转为数值。

var symbol = Symbol("Alice");
console.log(symbol.toString()); // 输出:Symbol(Alice)
console.log(Boolean(symbol)); // 输出:Symbol(Alice)
if (symbol)
	console.log("YES"); // 输出:Yes
console.log(Number(symbol)); // 报错:TypeError


2、作为对象属性名的Symbol

由于每一个Symbol值都是不相等的,这意味着Symbol值可以用于对象的属性名,保证不会出现同名的属性,这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

对象的属性名可以有两种类型,一种是原来的字符串,另一种是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

通过方括号结构和Object.defineProperty,将对象的属性名指定为一个Symbol值。

方法一:

var name = Symbol();
var obj = {
	[name]: "Alice"
};

方法二:

var name = Symbol();
var obj = {};
obj[name] = "Alice";

方法三:

var obj = {};
Object.defineProperty(obj, name, { value: 'Alice' });

在对象的内部,使用Symbol值定义属性时,Symbol值必须放在方括号之中,如果不放在方括号中,该属性名就是字符串,而不是代表的Symbol值。

var name = Symbol();
var obj1 = {
	[name]: "Alice"
};
var obj2 = {
	name: "Bruce"
};
console.log(obj1.name); // 输出:undefined
console.log(obj1[name]); // 输出:Alice
console.log(obj2.name); // 输出:Bruce
console.log(obj2[name]); // 输出:undefined

Symbol值作为对象属性名时,不能用点运算符。由于点运算符后面总是字符串,所以不会读取name作为标识名所指代的那个值,导致属性名实际上是一个字符串,而不是一个Symbol值。

var obj = {};
var name = Symbol();
obj.name = 'Alice';
console.log(obj.name);
console.log(obj[name]);
console.log(obj['name']);


3、作为对象函数名的Symbol

var func = Symbol();
var obj = {
	func: function() {
		console.log("YES");
	}
};
obj.func(); // 输出:YES


4、获取对象属性的两种方法

1) Object.getOwnPropertySymbols()方法

返回只包含Symbol类型的属性名的数组

2) Object.getOwnPropertyNames()方法

返回只包含字符串类型的属性名的数组

var obj = {};
var age = Symbol("age");
var job = Symbol("job");
obj[age] = "Alice";
obj[job] = "student";
obj.age = 23;
var symbols = Object.getOwnPropertySymbols(obj);
var names = Object.getOwnPropertyNames(obj);
console.log(symbols.length); // 输出:2
console.log(symbols); // 输出:[Symbol(age), Symbol(job)]
console.log(obj[symbols[0]]); // 输出:Alice
console.log(names.length); // 输出:1
console.log(obj[names[0]]); // 输出:23


5、Symbol.for()和Symbol.keyFor()方法

1) Symbol.for()方法

类似于单例模式,首先在全局中搜索有没有以该参数为名称的Symbol值,如果有则返回该Symbol值,否则新建并返回一个以该参数为名称的Symbol值。

var symbol1 = Symbol.for('Alice');
var symbol2 = Symbol.for('Alice');
console.log(symbol1 === symbol2) // 输出:true

2) Symbol.keyFor()方法

返回一个已创建的Symbol类型值的key,实质是检测该Symbol是否已创建。

var symbol1 = Symbol.for("Alice");
console.log(Symbol.keyFor(symbol1)); // 输出:"Alice"
var symbol2 = Symbol("Alice");
console.log(Symbol.keyFor(symbol2)); // 输出:undefined
### 作用 SymbolES6 中引入的一种新的原始数据类型,其主要作用是表示独一无二的值。这种值可以用来作为对象属性的键,从而确保属性键的唯一性,避免命名冲突。Symbol 类型的值是不可变的,并且不能与其他数据类型进行运算,包括字符串拼接[^1]。 ### 使用场景 1. **解决命名冲突** Symbol 最常见的使用场景是作为对象属性的键,以确保属性键的唯一性。例如,在一个大型应用中,多个模块可能会定义相同的属性名,使用 Symbol 可以避免这种冲突。 ```javascript let symbol1 = Symbol("key"); let symbol2 = Symbol("key"); console.log(symbol1 === symbol2); // 输出:false ``` 2. **私有属性** Symbol 可以用来定义对象的私有属性,这些属性不会被普通的遍历方法(如 `for...in` 或 `for...of`)遍历到。 ```javascript let obj = { username: 'xiaozhan', age: 29 }; let symbol = Symbol("hello"); obj[symbol] = "hello"; console.log(obj); // 输出:{ username: 'xiaozhan', age: 29, [Symbol(hello)]: 'hello' } for (let i in obj) { console.log(i); // 输出:username, age } ``` 3. **常量定义** Symbol 可以用来定义常量,确保常量的唯一性。 ```javascript const The_Key = Symbol('the_key'); console.log(The_Key); // 输出:Symbol(the_key) ``` 4. **全局共享的Symbol值** 使用 `Symbol.for()` 方法可以在全局环境中查找或创建一个 Symbol 值,确保在不同的代码部分中使用相同的 Symbol 值。 ```javascript let s1 = Symbol.for('foo'); let s2 = Symbol.for('foo'); console.log(s1 === s2); // 输出:true ``` 5. **内置Symbol值** ES6 提供了多个内置的 Symbol 值,用于指向语言内部的方法。例如,`Symbol.iterator` 指向对象的默认遍历方法。 ```javascript let symbol = Symbol.iterator; console.log(symbol); // 输出:Symbol(Symbol.iterator) ``` ### 注意事项 - **不能使用点运算符** Symbol 值作为对象属性名时不能使用点运算符,必须放在方括号中。 ```javascript var s = Symbol(); var obj = { [s]: function(arg) { /* ... */ } }; obj[s](123); // 正确调用 ``` - **不参与运算** Symbol 值不能与其他数据类型进行运算,包括字符串拼接。 ```javascript let symbol = Symbol("hello"); // console.log(symbol + "world"); // 报错:Cannot convert a Symbol value to a string ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值