属性描述符给js添加了庞大的可能性,要想搞懂前端3大框架道理,不懂不可啊。
对象属性
Object.getOwnPropertyDescriptor()
此函数传入两个参数,一个是目标对象,一个是目标对象的属性,返回的是一个该属性的属性描述符对象,就像如许。
var obj = {test: 'test'}
console.log(Object.getOwnPropertyDescriptor(obj, 'test'))
// 输出
{ value: 'test',
writable: true,
enumerable: true,
configurable: true
}
// 发起列位看官,本身着手试一下噢
能够看到,假如是用字面量声明的对象,默许 writable enumerable configurable 的值都是true
Object.defineProperty()
此函数传入3葛参数,第一个是目标对象,第二个是要修正的目标对象的属性(能够是目标对象没有的属性),第三个是属性描述符对象,
下面我们来修正一下wratable 属性描述符,看看会发作什么?
Object.defineProperty(myObject, 'test', {
writable: false
})
myObject.a = 'test again'
console.log(myObject)// {test: 'test'} ???
oh 我的again呢?
在writable 为false 的时刻,js会疏忽掉 该属性的赋值行动,我去太坑了,不可也不通知我一声。(若想他通知你,请使用严厉形式)
假如我 define 一个不存在的属性的property呢?就像如许
Object.defineProperty(myObject, 'test2', {
value: 'testtest'
})
console.log(Object.getOwnPropertyDescriptor(myObject, 'test2'))
// 输出
{ value: 'testtest',
writable: false,
enumerable: false,
configurable: false
}
我去,定义一个不存在的属性会建立一个只要value, 其他描述符都为false的属性,如许定义的属性,其他描述符默许为false(超等平安)
如今来尝尝 修正configurable吧
Object.defineProperty(myObject, 'test', {
configurable: false,
value: 'testconfigurable',
enumerable: true,
writable: false
})
Object.defineProperty(myObject, 'test', {
writable: true
})
myObject.test = 'config writable after set the configurable flase';
console.log(Object.getOwnPropertyDescriptor(myObject, 'test'))
console.log(myObject.test) // error: cant not redefine.....
噢 报错了,我们把configurable 修正的同时 把 wriable 也弄成false了,然后 再把writable 给弄返来ture 发明报错了,本来 configurable 是不让我们修正 test 这个属性的描述符了吗?
我们再来试一下,先修正configurable 再动 writable。
Object.defineProperty(myObject, 'test', {
configurable: false,
value: 'testconfigurable',
enumerable: true,
writable: true
})
Object.defineProperty(myObject, 'test', {
writable: false
})
myObject.test = 'config writable after set the configurable flase';
console.log(Object.getOwnPropertyDescriptor(myObject, 'test'))
console.log(myObject.test) // testconfigurable
我的天啊,what happen 赋值失利??? writable false 见效? 什么情况。。。 只许州官放火,不许百姓点灯啊(不知道是bug,照样尚有缘由,不过谁让他是js,就是这么奇异)
既然是不可修正属性,那我直接移除了呢?就像如许
var myObject = {test: 'test'}
console.log(myObject) // test
delete myObject.test
console.log(myObject.test) // undefined
// myObject.a = 'bbb'
myObject.test = 'test';
Object.defineProperty(myObject, 'test', {
configurable: false,
value: 'testconfigurable',
enumerable: true,
writable: true
})
console.log(myObject) // testconfigurable
delete myObject.test
console.log(myObject) // testconfigurable
能够看到,你删我不到~,你删我不到~
enumerable (可罗列的)
照旧
var myObject = {test: 'test'}
Object.defineProperty(myObject, 'test', {
configurable: false,
value: 'testconfigurable',
enumerable: false,
writable: true
})
console.log(myObject)
// 输出
{ value: 'testconfigurable',
writable: true,
enumerable: false,
configurable: false }
{}
?? 我的属性呢? 莫得了? 然则描述符在啊? value 也在啊
enumerable 是掌握属性是否能 照旧显现的描述符,若为false 不单只console.log 不出来 就连 forin 轮回也不会遍历到他的key值
好了,一切的属性描述符的性子都已引见过了,我们已知道了他们是什么了,然则这些描述符有什么用呢?为何须要这些描述符呢?
建立不可变的对象
试想一下,在没有属性描述符的时刻,怎样处理对象这类援用范例的不可变?不可能。。。
上面我们已说过,当一个属性被设置为configurable 为 false 的时刻,该属性不能被删除,当我们设置writable 为false 的时刻,该属性不能被修正,嗯?,这不就是不可变的吗,上文演示的是字符串,那我们来测试一下对象吧
var myObject = {test: {}}
Object.defineProperty(myObject, 'test', {
configurable: false,
enumerable: true,
writable: false
})
myObject.test.test = 'test'
console.log(myObject)// {test: {test}: 'test'}
我去,不可啊,照样写进去了,岂非要用递归把他悉数的子属性的子属性都如许定义一遍?
不怕,官方有新的API 来支撑这一个功用
Object.preventExtendsions(myObject)
该函数接收一个对象,该对象变得不可扩大
var myObject = {
a: 2
};
Object.preventExtensions( myObject );
myObject.b = 3;
myObject.b; // undefined
var anotherObj = {test: {}}
Object.preventExtensions( anotherObj);
anotherObj.test.test = 3;
anotherObj.test.test; // 3
从这段代码,能够看到 preventExtensions 仅仅是支撑 顶层对象的不可扩大,并不能限定子层对象的扩大。
seal() 封印
Object.seal(myObjct) 会把myObject 的一切属性的 configurable 都设置为false(注重writable 照样为true的),而且都不可扩大。(然则子层援用属性依然能被修正)
freeze() 凝结
Object.freeze(myObjct) 会把myObject 的一切属性的 configurable 都设置为false writable 为false,而且都不可扩大。(然则子层援用属性依然能被修正),这是你能在js中取得的最不可变的对象了。
接见器描述符
对象描述符,除了属性描述符之外,另有一种接见器描述符。
get
Object.defineProperty(myObject, 'test', {
get () {
console.log('获取值')
return 'testsetestest'
}
})
myObject.test = 222;
console.log(myObject.test);
// 输出
获取值
testsetestest
set
Object.defineProperty(myObject, 'test', {
get () {
console.log('获取值')
return this.test2
},
set (val) {
console.log('设置值')
this.test2 = val
}
})
myObject.test = 'ttttttt'
console.log(myObject.test2)f // ttttttt
综合上面两段代码来看,当我们给该属性设置了get,然后再给该属性赋值时,js会实行get要领 而且 把赋的值给疏忽掉,假如我们要让get 和 set 根据一般的头脑工作起来,就要借助别的一个属性 来到达一般操纵的目标。觉得这有点儿像 vue 中 watch 和 computed 的头脑工作方式,说不定他们有很大的关联。
好了,本日就到这吧,关于对象更深切的就是原型链了,这个东西要说的话就另起一篇吧,不然这文章就太长了撒。