ES6中新增Symbol

ES5的对象属性名都是字符串,这容易造成属性名的冲突。ES6引入一种新的原始数据类型Symbol,表示独一无二的值。它是Javascript的第七种数据类型。其他六种为Undefined、Null、String、Boolean、Number、Object。
对象的属性名现在可以有两种类型:
一是原来就有的字符串类型,二新增的Symbol类型。只要属性名属于Symbol类型,就是独一无二的。

let s=Symbol();
typeof s;//"symbol"

Symbol函数的参数只表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的。

//没有参数的情况
var s1=Symbol();
var s2=Symbol();
s1===s2//false
var s3=Symbol('foo');
var s4=Symbol('foo');
s3===s4//false
//Symbol不能与其他类型的值进行运算,否则会报错。Symbol可以显式转为字符串,也可以转为布尔值,但是不能转为数值
var sym=Symbol('symbol');
sym.toString();//'Symbol('symbol')'
Boolean(sym);//true
Number(sym);//TypeError

由于每一个Symbol值都是不相等的,这就意味着Symbol值可以作为标识符用于对象的属性保证不会出现同名属性。
将对象的属性指定为一个Symbol值

var symbol=Symbol();
//第一种方法
var a={};
a[symbol]='happy';
//第二种方法
var a={
	[symbol]:'happy';
}
//第三种方法
var a={};
Object.definedProperty(a,symbol,{value:'happy'});
a[symbol]//'happy'

注意:Symbol值作为对象属性名时不能使用点运算符。
在对象内部,使用Symbol值定义属性时,Symbol值必须放在方括号中。

var s=Symbol();
var obj={
	[s]:function(arg){...}
}
obj[s](123);
//也可以简写为
var obj={
	[s](arg){...}
}

Symbol类型还可用于定义一组常量,保证这组常量的值都是不相等的

log.levels={
	DEBUG:Symbol('debug'),
	INFO:Symbol('info'),
	WARN:Symbol('warn')
};
log(log.levels.DEBUG,'debug message');
log(log.levels.INFO,'info message');

Object.getOwnPropertySymbols方法可以获取指定对象的所有Symbol属性名。返回一个数组,成员是当前对象的所有用作属性名的Symbol值。

var obj={};
var a=Symbol('a');
var b=Symbol('b');
obj[a]='happy';
obj[b]='day';
var s=Object.getOwnPropertySymbols(obj);
s//[Symbol(a),Symbol(b)]

如果希望使用同一个Symbol值,Symbol.for方法可以做到这一点。它接收一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。

var s1=Symbol.for('foo');
var s2=Symbol.for('foo');
s1===s2//true

Symbol()写法没有登记机制,所以每次调用都会返回一个不同的值,Symbol.keyFor()方法返回一个已登记的Symbol类型值的key。

var s=Symbol.for("foo");
Symbol.keyFor(s1);//"foo"
var ss=Symbol("foo");
Symbol.keyFor(ss);//undefined

注意
Symbol不能new
Symbol()返回是一个唯一值
Symbol是一个单独数据类型,就叫基本类型
如果Symbol作为key,用for…in循环不出来

内置的Symbol的值
1.Symbol.hasInstance
对象使用instanceof运算符时会调用这个方法,判断对象是否为某个构造函数的实例,比如 foo instanceof Foo,在语言内部实际调用的是FooSymbol.hasInstance

class A{
	[Symbol.hasInstance](foo){
		return foo instanceof Array;
	}
}
[1,2,3] instanceof new A();//true

2.Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable属性是一个布尔值,表示该对象使用Array.prototype.concat()时是否可以展开。

var arr1=['b','c'];
['a'].concat(arr1,'d');//['a','b','c','d']
arr1[Symbol.isConcatSpreadable]//undefined

var arr2=['b','c'];
arr1[Symbol.isConcatSpreadable]=false;
['a'].concat(arr2,'d');//['a',['b','c'],'d']

3.Symbol.species
对象的Symbol.species属性指向当前的对象的构造函数。常在实例时默认会调用这个方法,即使用这个属性返回的函数当做构造函数来创造新的实例对象。

class A extends Array{
	static get[Symbol.species](){return Array;}
}
var a=new A(1,2,3);
var b=a.map(x=>x*x);
b instanceof A;//false
b instanceof Array;//true

4.Symbol.match
对象的Symbol.match属性指向一个函数,当执行str.match(obj)时,如果该属性存在,会调用它返回该方法的返回值。

class A{
	[Symbol.match](String){
		return 'happy'.indexOf(string);
	}
}
'a'.match(new A());//1

5.Symbol.replace
对象的Symbol.replace属性指向一个方法,当对象被String.prototype.replace方法调用时会返回该方法的返回值。

var obj={};
obj[Symbol.replace]=(...s)=>console.log(s);
'hello'.replace(obj,'world');//['hello','world']

6.Symbol.search
对象的Symbol.search属性指向一个方法,当对象被String.prototype.search方法调用时会返回该方法的返回值。

class A{
	constructor(value){
		this.value=value;	
	}
	[Symbol.search](string){
		return string.indexOf(this.value);	
	}
}
'happy'.search(new A('ha'));//0

7.Symbol.split
对象的Symbol.split属性指向一个方法,当对象被String.prototype.split方法调用时会返回该方法的返回值。

class A{
	constructor(value){
		this.value=value;	
	}
	[Symbol.split](string){
		var index=string.indexOf(this.value);	
		if(index===-1){return string;}
		return [
			string.substr(0,index);
			string.substr(index+this.value.length)
		];
	}
}
'happy'.split(new A('pa'));//['h','py']

8.Symbol.iterator
对象的Symbol.iterator属性指向该对象的默认值遍历器方法。

var obj={};
obj[Symbol.iterator]=function* (){
	yield 1;
	yield 2;
	yield 3; 
};
console.log([...obj]);//[1,2,3]

9.Symbol.toPrimitive
对象的Symbol.toPrimitive属性指向一个方法,当对象被转为原始类型的值时会调用这个方法,返回对象对应的原始类型值。

var obj={
	[Symbol.toPrimitive](hint){
		switch(hint){
			case:'number':
				return 123;
			case:'string':
				return 'str';
			case:'defalut':
				return 'defalut';
			default:
				throw new Error();	
		}
	}
};
2*obj//234
3+obj//'3+default'
obj==='default'//true
String(obj)//'str'

10.Symbol.toStringTag
对象的Symbol.toStringTag属性指向一个方法,在对象上调用Object.prototype.toString方法时,如果这个属性存在,其返回值出现在toString方法返回的字符串中,表示对象的类型。也就是说,这个属性可用于制定[object Object]或[object Array]中object后面的字符串。

({[Symbol.toStringTag]:'Foo'}.toString())
//[object Foo]

11.Symbol.unscopables
对象的Symbol.unscopables属性指向一个对象,指定了使用with关键字时哪些属性会被with环境排除。

Array.prototype[Symbol.unscopables]
//{
// copyWithin:true,
//entries:true,
//fill:true,
//find:true,
//findindex:true,
//includes:true,
//keys:true
//}
Object.keys(Array.prototype[Symbol.unscopables])
//['copyWithin','entries','fill','find','findIndex','includes','keys']
//没有unscopables时
class A{
	foo(){return 1;}
}
var foo=function(){return 2;}
with(A.prototype){
	foo();//1
}
//有unscopables时
class A{
	foo(){return 1;}
	get [Symbol.unscopables](){
		return {foo:true};
	}
}
var foo=function(){return 2;}
with(A.prototype){
	foo();//2
}

注:内容参考ES6标准入门第三版阮一峰著

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值