理清javascript对象进阶(描述符,封印,凝结)

属性描述符给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 的头脑工作方式,说不定他们有很大的关联。

好了,本日就到这吧,关于对象更深切的就是原型链了,这个东西要说的话就另起一篇吧,不然这文章就太长了撒。

    原文作者:les_lee
    原文地址: https://segmentfault.com/a/1190000015723158
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞