JS学习笔记Web前端之路让前端飞

<JS>Object.defineProperty(

2017-06-14  本文已影响30人  泡沫的快乐

只是按照我所理解的进行说明。
该方法运行更加精确控制对象的属性。

>>语法
Object.defineProperty(obj, attr, descriptor)
1: obj:要在其上定义属性的对象。
2: attr:要定义或修改的属性的名称。只能定义一个。
3: descriptor:将被定义或修改的属性描述符(具体看下面👇)。

要同时定义多个属性可使用 Object.defineProperties()

>>属性描述符
属性描述符分为: 数据描述符 和 存取描述符.

>>数据描述符,存取描述符 共有可选键值:
configurable: 当该属性为 true 时,该属性描述符才能够被改变,该属性也能够被删除。默认为 false。
若手动设置为false,那就再也无法修改任何描述符(除writable描述符要设置为false时)!
enumerable: 当该属性 为 true 时,该属性才能够出现在对象的枚举属性中(是否能在for...in, Object.keys()中被枚举)。默认为 false。

>>数据描述符 可选键值:
value: 该属性的值。 (可以是任何JS有效值)。 默认为undefined。
writable: 概述为true时,赋值运算符赋值才会成功。默认为false。

>>存取描述符 可选键值:
get: 在获取该属性的值时 调用的函数,该方法返回值作为属性的值。 默认为undefined。
set: 在修改该属性的值时 调用的函数(默认传入修改的值)。  默认为undefined。
注意

1: 在用Object.defineProperty()设置时,只能同时对一类型描述符进行设置。否则会报错。 测试:

let o = {};
Object.defineProperty(o, 'test', {
    value:1, //数据描述符
    get(){ // 存取描述符.
        return '测试'
    }
});//会报错,因为不能同时对 两种类型的描述符进行操作.

2: 正常创建属性。描述符都会被赋值,而不是默认值。
下面用这个方法——Object.getOwnPropertyDescriptor()
查询描述符信息。测试:

let o = {
    test:1
}// 可能你会以为,描述符会被赋值为上面所写的默认值。
let info = Object.getOwnPropertyDescriptor(o,'test');
console.log(info) 
/* 显示信息如下
 * configurable:true
 * enumerable:true
 * value:1
 * writable:true 
 */
在正常创建属性时,描述符都会被赋值。 大概情况为:
configuraable, enumerable, writable, 赋值为true.
value为所赋的值.

3: 描述符会被赋值为默认值的情况

>>数据描述符 设置为默认值
let o = {}  // 在使用↓方法时,没有写的描述符,会被赋值为默认值。
Object.defineProperty(o, 'test', {}); //默认设置数据描述符
let info = Object.getOwnPropertyDescriptor(o,'test'); //获取描述符信息
console.log(info) 
/* 显示信息如下
 * configurable:false
 * enumerable:false
 * value:undefined
 * writable:false
 */
set, get方法应该还是正常返回值,修改值。

>>存取描述符 设置为默认值
let o = {};
Object.defineProperty(o, 'test', {
    set(){} // 因为默认会设置数据描述符的默认值,所以设置下get, 让set为默认值。
})
let info = Object.getOwnPropertyDescriptor(o,'test');
console.log(info);
/* 显示信息如下
 * configurable:false
 * enumerable:false
 * set:function set() //我手动设置的
 * get:undefined //默认值
 */

重点:如果属性是通过此方法设置的,那么没有主动设置的描述符键值,它会被设置为,默认值(导致属性无法访问,无法修改)。
所以要记得在使用此方法定义属性时,给必要描述符键值进行设置,除非默认值符合你预期。
>>实践
简单写一个数据双向绑定.(不需要记忆,只是展示其功能)
function getAndSet(obj, attr, getFn, setFn){
    let nowVal = obj[attr];
    Object.defineProperty(obj, attr, {
        configurable:true,
        enumerable:true,
        get(){
            getFn(nowVal) // 在获取时调用的方法
            //可以写DOM操作,使其在数据改变的时候,DOM相应改变
            return nowVal
        },
        set(newVal){
            setFn(newVal, nowVal) // 在修改时调用的方法
            //可以写DOM操作,使其在数据改变的时候,DOM相应改变

            nowVal = newVal;
            return newVal
        },
    })
}
let o = {
    test:1
};
getAndSet(o, 'test', function(nowVal){
    console.log(`get方法! 值:${nowVal}`)
},function(newVal, nowVal){
    console.log(`set方法! 新值:${newVal},原值:${nowVal}`)
})
o.test // get方法! 值:1
o.test = 4 // set方法! 新值:4,原值:1

当属性值是对象时,函数就没效果了。毕竟只是简单的实现,你可以让其的所有属性再次去调用此方法。
更加复杂,强大的实现,可以去学Vue框架。

以上是我所知的的东西,有任何错误,请在评论指出!
O(∩_∩)O谢谢你的观看~

上一篇 下一篇

猜你喜欢

热点阅读