ES6的对象操作
1、Symbol
object的键都是字符串,且都是唯一的,不能重复。假设,我们使用一个别人提供的object,但是需要给这个object添加一个新的键值对,自己添加的键就有可能会跟object中原本的键冲突。symbol的主要作用就是创建对象中独一无二的键,可以从根本上防止对象中的键重复。
也就是说,对象中的键除了是字符串以外,还可以是symbol数据。
symbol数据通过Symbol函数生成,语法如下:
var s = Symbol()
console.log(s);
console.log(typeof s);
输出结果:
Symbol是一个函数,但不是一个构造函数,如果将Symbol当做构造函数new使用,会报错。
var s = new Symbol()
console.log(s);
Symbol函数可以接受字符串参数,同一个字符串得出的两个symbol是不相等的,这样就保证了每一个symbol数据都是独一无二的:
var s = Symbol('name')
var s1 = Symbol('name')
console.log(s == s1); // false
如果symbol的参数是一个对象,会默认调用对象的toString方法得到字符串:
var obj = {
name: '张三'
}
var s = Symbol(obj)
console.log(s);
var pbj = {
name: '李四',
toString: function(){
return this.name
}
}
var s1 = Symbol(pbj)
console.log(s1);
symbol数据作为对象的键使用,可以保证每个键都是唯一的:
var obj = {
name: '张三',
age: 12
}
// 想给对象添加name属性和age属性,可以对象中已经有了name属性和age属性了,此时就将name和age做成symbol数据,然后将symbol数据当做对象的键使用
// 通过name和age做成symbol数据
var nameSymbolKey = Symbol('name')
var ageSymbolKey = Symbol('age')
// 将symbol数据当做对象的键
obj[nameSymbolKey] = '李四'
obj[ageSymbolKey] = 13
console.log(obj);
symbol数据不能跟其他数据进行运算,不能进行隐形类型转换:
var s = Symbol(0)
var sum = s + 2
console.log(sum);
其他隐形转换都会报错:
var s = Symbol(0)
var str = s + 'abc' // 报错
console.log(Number(s)) // 报错
Symbol可以强制转换成字符串和布尔值:
var s = Symbol()
console.log( String(s) );
console.log(s.toString());
console.log(Boolean(s));
通过symbol数据的description属性得到symbol数据创建时的字符串参数:
var s = Symbol('abc')
console.log(s.description) // abc
2、Reflect
解决对象访问、修改、删除后我们无法知道是否成功的问题。
问题:当一个对象封闭后,无法添加属性,但我们并不知道是否添加成功
var obj = {
name: '张三'
}
Object.seal(obj)
obj.age = 12
console.log(obj);
结果没有给将age添加到obj上,假设我们并不知道这个对象是封闭的,添加了属性但没添加成功,我们会觉得莫名其妙。删除和修改同理。
使用Reflect进行添加、修改、删除就能知道是否成功了,语法:
Reflect.get(对象, 键) // 返回值或undefined
Reflect.set(对象, 键, 值) // 给对象添加键值对,返回布尔值
Reflect.deleteProperty(对象, 键) // 删除对象键值对,返回布尔值
例:
ar obj = {
name: '张三'
}
Object.seal(obj)
// 添加
var bool1 = Reflect.set(obj, 'age', 12)
console.log(bool1); // false
// 删除
var bool2 = Reflect.deleteProperty(obj, 'name')
console.log(bool2); // false
// 访问
var bool3 = Reflect.get(obj, 'name')
console.log(bool3); // '张三'
var bool3 = Reflect.get(obj, 'aaa')
console.log(bool3); // undefined
var pbj = {
name: '李四'
}
// 添加
var bool1 = Reflect.set(pbj, 'age', 12)
console.log(bool1); // true
// 删除
var bool2 = Reflect.deleteProperty(pbj, 'name')
console.log(bool2); // true
Reflect是将对象基本操作换成了函数写法,有了返回值,方便我们进行判断了。
3、Proxy
创建一个被劫持/监听的对象,当访问、设置、删除对象键值对的时候会被监视到,和defineProoerty的功能是一样的。语法:
var obj = {
name: '张三'
}
var pbj = new Proxy(obj, {
get(object, key) {
console.log(object, key);
return 111
},
set(object, key, val) {
console.log(object, key, val);
}
})
pbj.name = '张三' // {name: '张三'} 'name' '张三'
console.log( pbj.name ); // {name: '张三'} 'name' 111
实现数据和视图的双向绑定:
<body>
<input type="text">
</body>
<script>
var input = document.querySelector('input')
var data = {
msg: '哈哈'
}
input.value = data.msg
var vm = new Proxy(data, {
get(obj, key) {
return input.value
},
set(obj, key, val) {
input.value = val
}
})
input.oninput = function() {
vm.msg = this.value
}
</script>