ES6个人笔记记录——Symbol

ES5 的对象属性名都是字符串,这容易造成属性名的冲突
比如,我们使用了一个他人提供的对象,
但又想为这个对象添加新的方法Cmixin 模式〉,
新方法的名字就有可能与现有方法产生冲突。 

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值
是第七种数据类型
1.Number
2.String
3.Undefined
4.Null
5.Boolean
6.Object

Symbol值是通过Symbol函数生成,
只要属性名属于Symbol类型,就是独一无二的,
可以保证不会与其他属性名冲突
let s1 = Symbol();
console.log(typeof s1);
PS:Symbol函数不能使用new命令,
	因为生成的Symbol是一个原始类型的值,不是对象
	就是说Symbol不是对象,所以不能添加属性
	基本上,他是一种类似于字符串的数据类型
// Symbol添加参数,便于区分
let s2 = Symbol('foo');
let s3 = Symbol('bar');

console.log(s2,s3);

// eg1
let mySymbol = Symbol();
let mySymbol2 = Symbol();
let mySymbol3 = Symbol();

// 第一种写法
let a = {};
a = {
	[mySymbol2] : 'world'
}

// 第二种写法
a[mySymbol] = 'hello';

// 第三种写法	不太行
Object.defineProperty(a,mySymbol3,{value : 'wjy'});

console.log(a)

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

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

// 例子:消除魔术字符串
function getArea(shape,options){
	let area = 0;

	switch(shape){
		case 'Triangle': 	//魔术字符串
			area = .5 * options.width * options.height;
			break;
		default:
			area = "false";
			break;
	}
	return area;
}

强耦合

console.log(getArea('Triangle',{width : 100,height : 200}));

// change
function getAreaChange(shape,options){
	let area = 0;
	let { PI } = Math;
	switch(shape){
		case shapeType.triangle:
			area = .5 * options.width * options.height;
			break;
		case shapeType.circle:
			area = PI * options.radius ** 2;
			break;
		default:
			area = "false";
			break;
	}
	return area;
}

let shapeType = {
	// triangle : 'Triangle'
	/*
		经过分析可知,shapeType.triangle等于哪个值不重要
		只要确保不会和其他shapeType属性的值冲突即可
	 */
	triangle : Symbol(),
	circle : Symbol()
};

console.log(getAreaChange(shapeType.triangle,{ width : 200, height : 3}));
console.log(getAreaChange(shapeType.circle,{ radius : 2 }));

属性名的遍历

let {  getOwnPropertyNames , getOwnPropertySymbols , defineProperty } = Object;
let objectSymbols1 = getOwnPropertySymbols(a);
console.log(objectSymbols1)

// another example
let obj3 = {};
let foo3 = Symbol("foo");
defineProperty(obj3,foo3,{
	value : "foobar",
});

for(let i in obj3){
	console.log(i);		//无输出
}
使用getOwnPropertyNames方法得不到Symbol属性名
需要使用getOwnPropertySymbols方法
console.log(getOwnPropertyNames(obj3));
console.log(getOwnPropertySymbols(obj3));
可以使用Reflect.ownKeys()方法返回所有类型的键名
包括常规键名和Symbol键名
const { ownKeys } = Reflect;

let obj4 = {
	[Symbol('my_key')]: 1,
	enum : 2,
	nonEnum : 3
};

console.log(ownKeys(obj4));
以Symbol值作为名称的属性不会被常规方法遍历得到。
我们可以利用这个特性为对象定义些非私有但又希望只用于内部的方法。
let size = Symbol('size');

class Collection{
	constructor(){
		this[size] = 0;
	}

	add(item){
		this[this[size]] = item;
		this[size]++;
	}

	static sizeOf(instance){
		return instance[size];
	}
}

let x = new Collection();
console.log(Collection.sizeOf(x));
x.add('foo');
console.log(Collection.sizeOf(x))

const { keys , getOwnPropertySymbols , getOwnPropertyNames } = Object;
console.log(keys(x),getOwnPropertyNames(x),getOwnPropertySymbols(x));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值