强大的Object.defineProperty详解

强大的JS方法Object.defineProperty详解

Object.defineProperty是一个很了不起的方法。vue.js之所以能够实现双向绑定便是拜它所赐!defineProperty直接翻译过来即是“定义属性”,不过该方法可不仅仅是定义属性这么简单,咱们还可以通过它来对属性进行拦截设置!

var obj={};//或obj=new Object;
// 添加属性(描述)
obj.userName="laotie";//或 obj["userName"]="laotie"
// 添加方法(行为)
obj.run=function(){};//或 obj["run"]=function(){};

为对象增加属性的方法除了上面的方式外,咱们还可以通过Object.defineProperty来定义新属性,或者对原属性进行修改。

Object.defineProperty(obj, prop, descriptor):

  • obj:必需。目标对象
  • prop:必需。需定义或修改的属性的名字
  • descriptor:必需。目标属性所拥有的特性

两个参数不多说了,看代码就明白了,我们主要看第三个参数descriptor

1、 value

通过value可以为对象设置属性,对应的值可以是任意类型,默认为undefined

var obj={};
console.log(obj.userName);// undefined
Object.defineProperty(obj,"userName",{
    value:"zhouyajing"
});
console.log(obj.userName);// zhouyajing

可以对原有值进行修改

var obj={};
obj.userName="laoli"
console.log(obj.userName);// laoli
Object.defineProperty(obj,"userName",{
    value:"zhouyajing"
});
console.log(obj.userName);// zhouyajing

返回的值为传入函数的对象,即第一个参数obj

var obj={};
var obj2=Object.defineProperty(obj,"userName",{
    value:"laozhang"
});
console.log(obj==obj2);// true

2、writable

用于设置属性的值是否允许被重写。true为允许,false不允许被重写,默认为false

设置为false不允许被重写,并没有错误抛出

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    writable:false
});
obj.userName="laoliu";
console.log(obj.userName);// zhouyajing

如果在严格描述下会报错

"use strict";
var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    writable:false
});
obj.userName="laoliu";
//报错:TypeError: Cannot assign to read only property 'userName' of object

默认为false,值不允许被修改

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing"
});
obj.userName="laoliu";
console.log(obj.userName);// laozhang

设置为true,允许被修改

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    writable:true
});
obj.userName="laoliu";
console.log(obj.userName);// laoliu

2、enumerable

该描述决定着指定的属性是否允许被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false

设置为false不允许被枚举

var obj={
	age:18
};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    writable:false,
    enumerable:false
});
for(var key in obj){
    console.log(key,obj[key])// age 18
}
console.log(Object.keys(obj));//[ 'age' ]

默认值为false, 不允许被枚举

var obj={
	age:18
};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    writable:false
});
for(var key in obj){
    console.log(key,obj[key])// age 18
}
console.log(Object.keys(obj));//[ 'age' ]

设置为true,允许被枚举

var obj={
    age:18
};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    writable:false,
    enumerable:true
});
for(var key in obj){
    /*  age 18 
        userName zhouyajing*/ 
    console.log(key,obj[key]);
}
console.log(Object.keys(obj));//[ 'age', 'userName' ]

4、configurable

configurable是一个总开关,一旦你将它设置为false,就不能删除指定的属性也不能再设置他的(value,writable,configurable),设置为true,允许被删除,也允许被设置

为false不允许被删除,不会报错

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    configurable:false
});
delete obj.userName;
console.log(obj.userName);//zhouyajing

为false不允许被重新设置,会报错

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    configurable:false
});
Object.defineProperty(obj,"userName",{
    value:"laoli"
});
//报错:TypeError: Cannot redefine property: userName

为true时,允许被删除

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    configurable:true
});
delete obj.userName;
console.log(obj.userName);//undefined

为true时,允许被重新设置

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zhouyajing",
    configurable:true
});
Object.defineProperty(obj,"userName",{
    value:"laoli"
});
console.log(obj.userName);//laoli

5、get/set存取器描述

当你需要设置或获取对象的某个属性值的时候,可以使用该方法。

var obj={};
var initValue="zzz";
Object.defineProperty(obj,"userName",{
    get(){
        // 当读取userName时会有输出
        console.log("执行了get");
        return initValue;
    },
    set(newValue){
        // newValue为写入的值
        console.log("执行了set");
        initValue= newValue+"吧!"
    }
});

/*  执行了get
    zzz */
console.log(obj.userName);

obj.userName="zhouyajing";// 执行了set

/*  执行了get
    zhouyajing */
console.log(obj.userName);

get或set不是必须成对出现,任写其一就可以

var obj={};
Object.defineProperty(obj,"userName",{
    get(){
        return "zhouyajing"
    }
});
console.log(obj.userName);//zhouyajing

当使用了get或set方法,不允许使用writable和value这两个属性

var obj={};
Object.defineProperty(obj,"userName",{
    value:"zzz",
    get(){
        return "zhouyajing"
    }
});
console.log(obj.userName);
//报错:Invalid property descriptor. Cannot both specify accessors and a value or writable attribute

实例

var obj={};
var userName="";
var userArr=[];
Object.defineProperty(obj,"userName",{
    get(){
        return userName;
    },
    set(value){
        userArr.push(value);
        userName=value;
    }
});
obj.userName="张三";
obj.userName="李四";
obj.userName="王五";
console.log(userArr);// [ '张三', '李四', '王五' ]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值