转载:https://www.jianshu.com/p/8fe1382ba135
讲解大体会根据下图展开javascript
本文部分参考了书籍《你不知道的javascript》上卷java
常用的定义与赋值方法obj.prop =value
或者obj['prop']=value
bash
Object.defineProperty()
的做用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性函数
Object.defineProperty(obj, prop, desc)
复制代码
通常经过为对象的属性赋值的状况下,对象的属性能够修改也能够删除,可是经过Object.defineProperty()定义属性,经过描述符的设置能够进行更精准的控制对象属性。学习
javacript 有三种类型的属性ui
getter
和setter
进行读取和赋值的属性[[Prototype]]
,你不能直接访问这个属性,但能够经过Object.getPrototypeOf()
方法间接的读取到它的值。虽然内部属性一般用一个双吕括号包围的名称来表示,但实际上这并非它们的名字,它们是一种抽象操做,是不可见的,根本没有上面两种属性有的那种字符串类型的属性经过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符,下面分别描述下二者的区别:spa
let Person = {}
Object.defineProperty(Person, 'name', {
value: 'jack',
writable: true // 是否能够改变
})
复制代码
注意,若是描述符中的某些属性被省略,会使用如下默认规则:3d
get
:一个给属性提供getter
的方法,若是没有getter
则为undefined
。该方法返回值被用做属性值。默认为undefined
。set
:一个给属性提供setter
的方法,若是没有setter
则为undefined
。该方法将接受惟一参数,并将该参数的新值分配给该属性。默认值为undefined
。code
let Person = {}
let temp = null
Object.defineProperty(Person, 'name', {
get: function () {
return temp
},
set: function (val) {
temp = val
}
})
复制代码
从以上代码运行结果分析总结可知:orm
- configurable: false 时,不能删除当前属性,且不能从新配置当前属性的描述符(有一个小小的意外:能够把writable的状态由true改成false,可是没法由false改成true),可是在writable: true的状况下,能够改变value的值
- configurable: true时,能够删除当前属性,能够配置当前属性全部描述符。
注意:如下二种区别
在非严格模式下,建立属性gender会静默失败,在严格模式下,将会抛出异常。
因此, 密封以后不只不能添加新属性,也不能从新配置或者删除任何现有属性(虽然能够改属性的值)
冻结
Object.freeze()会建立一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(),并把全部现有属性标记为writable: false,这样就没法修改它们的值。
这个方法是你能够应用在对象上级别最高的不可变性,它会禁止对于对象自己及其任意直接属性的修改(可是这个对象引用的其余对象是不受影响的)
你能够深度冻结一个对象,具体方法为,首先这个对象上调用Object.freeze()而后遍历它引用的全部对象,并在这些对象上调用Object.freeze()。可是必定要当心,由于这么作有可能会无心中冻结其余共享对象。
最后一小节,总结一下上述内容
1: 将一个数据属性转换成访问器属性,反之变然
2: 改变`[[Configurable]]`或`[[Enumerable]]`
3: 改变[[Writable]]由false变为true
4: 在`[[Writable]]`为`false`时改变`[[Value]]`
5: 改变[[Get]]或[[Set]]
复制代码
P
的只读属性(只读的数据属性或者没有setter
的访问器属性),则拒绝P
的且拥有setter
的访问器属性,则调用这个setter
P
的自身属性,则若是这个对象是可扩展的,就建立一个新属性,不然,若是这个对象是不可扩展的,则拒绝P
属性的值,其余的特性(好比可枚举性)都不会改变属性的定义操做和赋值操做各自有本身的做用和影响。
赋值可能会调用原型上的setter
,定义会建立一个自身属性。
原型链中的同名只读属性可能会阻止赋值操做,但不会阻止定义操做。若是原型链中存在一个同名的只读属性,则没法经过赋值的方式在原对象上添加这个自身属性,必须使用定义操做才能够。这项限制是在ECMAScript 5.1中引入的
赋值运算符不会改变原型链上的属性
不能经过为obj.foo
赋值来改变proto.foo
的值。这种操做只会在obj
上新建一个自身属性
对象字面量中的属性是经过定义操做添加的。
再次啰嗦一次,记住如下两种形式的区别:
上面的代码等同于:
另外一方面:
上面的代码等同于:
转载自:https://www.jianshu.com/p/8fe1382ba135,用于之后学习使用!