这是js中一个非常重要的方法,ES6中某些方法的实现依赖于它,VUE通过它实现双向绑定

此方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象

参数

Object.defineProperty(object, attribute, descriptor)

这三个参数都是必输项

第一个参数为目标对象

第二个参数为需要定义的属性或者方法

第三个参数为目标属性所拥有的特性

前两个参数都很明确,重点是第三个参数 descriptor, 它有以下取值

descriptor

value: 属性的值

writable: 属性的值是否可被重写(默认为false)

configurable: 总开关,是否可配置,若为false, 则其他都为false(默认为false)

enumerable: 属性是否可被枚举(默认为false)

get: 获取该属性的值时调用

set: 重写该属性的值时调用

一个例子

var a= {}
Object.defineProperty(a,"b",{
value:123
})
console.log(a.b) //
a.b = 456
console.log(a.b) //
a.c = 110
for (item in a) {
console.log(item, a[item]) //c 110
}

因为 writable 和 enumerable 默认值为 false, 所以对 a.b 赋值无效,也无法遍历它

configurable

总开关,是否可配置,设置为 false 后,就不能再设置了,否则报错, 例子

var a= {}
Object.defineProperty(a,"b",{
configurable:false
})
Object.defineProperty(a,"b",{
configurable:true
})
//error: Uncaught TypeError: Cannot redefine property: b

writable

是否可重写

var a = {};
Object.defineProperty(a, "b", {
value : 123,
writable : false
});
console.log(a.b); // 打印 123
a.b = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
console.log(a.b); // 打印 123, 赋值不起作用。

enumerable

属性特性 enumerable 定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举

var a= {}
Object.defineProperty(a,"b",{
value:3445,
enumerable:true
})
console.log(Object.keys(a));// 打印["b"]

enumerable改为false

var a= {}
Object.defineProperty(a,"b",{
value:3445,
enumerable:false //注意咯这里改了
})
console.log(Object.keys(a));// 打印[]

set 和 get

如果设置了 set 或 get, 就不能设置 writable 和 value 中的任何一个,否则报错

var a = {}
Object.defineProperty(a, 'abc', {
value: ,
get: function() {
return value
}
})
//Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object> at Function.defineProperty

对目标对象的目标属性 赋值和取值 时, 分别触发 set 和 get 方法

var a = {}
var b = 1
Object.defineProperty(a,"b",{
set:function(newValue){
b = 99;
console.log("你要赋值给我,我的新值是"+newValue);
},
get:function(){
console.log("你取我的值");
return 2 //注意这里,我硬编码返回2
}
})
a.b = 1 //打印 你要赋值给我,我的新值是1
console.log(b) //打印 99
console.log(a.b) //打印 你取我的值
//打印 2 注意这里,和我的硬编码相同的

上面的代码中,给a.b赋值,b的值也跟着改变了。原因是给a.b赋值,自动调用了set方法,在set方法中改变了b的值。vue双向绑定的原理就是这个。

扩展

Reflect.defineProperty()

可以使用ES6的静态方法 Reflect.defineProperty(), 使用起来和 Object.defineProperty 完全一样,唯一的不同是修改属性的配置出错时,返回false, 不抛错。  例子:

var a = {}
Reflect.defineProperty(a, "b", {
value: ,
configurable: false
})
Reflect.defineProperty(a, "b", {
value: ,
configurable: true
})
// 返回false
var a = {}
Reflect.defineProperty(a, "b", {
value: 2,
configurable: false
})
Object.defineProperty(a, "b", {
value: 2,
configurable: true
})
//Uncaught TypeError: Cannot redefine property: b at Function.defineProperty (<anonymous>) at <anonymous>:6:8

Object.defineProperties

此方法可以一次设置多个属性,例子:

var a = {}
Object.defineProperties(a, {
c: {
value: 1
},
d: {
value: 2
}
})
// 返回{c: 1, d: 2}

用Object.defineProperty实现黑科技

使 a==1 && a==2 && a==3 为true

var b = 1
Object.defineProperty(window, "a", {
get: function() {
return b++
}
})
console.log(a==1 && a==2 && a==3) //返回true

除此之外,还可以用对象的 toString() 方法来实现

var a = {
b: 1,
toString() {
return this.b++
}
}
console.log(a==1 && a==2 && a==3) //返回true

ps: 这是本人在博客园写的第一个博客,欢迎大家多对支持和提出意见建议

参考:https://www.cnblogs.com/weiqu/p/5860945.html

Object.defineProperty()方法学习笔记的更多相关文章

  1. Object.defineProperties()和Object.defineProperty()方法

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象. 语法:Object.defineProperty(obj, pro ...

  2. Object.defineProperty方法 使用

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象. 语法: Object.defineProperty(obj, pr ...

  3. Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 语法EDIT Object.defineProperty(obj, ...

  4. JavaScript Object.defineProperty()方法详解

    Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 语法 Object.defineProperty(obj, prop ...

  5. Object 对象方法学习之(1)—— 使用 Object.assign 复制对象、合并对象

    作用 Object.assign() 方法用于把一个或多个源对象的可枚举属性值复制到目标对象中,返回值为目标对象. 语法 Object.assign(target, ...sources) 参数 ta ...

  6. js中Object.defineProperty()方法的解释

    菜菜: “老大,那个, Object.defineProperty 是什么鬼?” 假设我们有个对象 user ; 我们要给它增加一个属性 name , 我们会这么做 1 2 3 var user = ...

  7. Vue el与data的两种写法 && Object.defineProperty方法

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  8. JavaScript使用Object.defineProperty方法实现双数据绑定

    Object.defineProperty这个方法非常值得学习,很多mvc框架中的双向数据绑定就是通过它来实现的. 本着互联网分享精神,今天我就将我自己的见解分享给大家,希望能有所帮助. 开始使用 O ...

  9. Object.defineProperty 相关学习

    Object.defineProperty 学习   描述: 方法直接在对象上定义一个新属性,或修改对象上的现有属性 并返回该对象.该方法允许精确地添加或修改对象上的属性: 语法: Object.de ...

随机推荐

  1. Centos 改ssh 端口

    1.修改配置文件:/etc/ssh/sshd_config 2.修改 #Port 22 把前面的#注释删掉,然后添加一个Port XXXX 定义一个自己的.例如我喜欢 Port 22333 3.修改后 ...

  2. log4j2配置文件log4j2.xml详解

    配置全解 1.缺省默认配置文件 <?xml version="1.0" encoding="UTF-8"?> <Configuration s ...

  3. 18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?

    在MySQL中,有很多看上去逻辑相同,但性能却差异巨大的SQL语句.对这些语句使用不当的话,就会不经意间导致整个数据库的压力变大. 我今天挑选了三个这样的案例和你分享.希望再遇到相似的问题时,你可以做 ...

  4. 重载new和delete运算符

    内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...

  5. The Preliminary Contest for ICPC China Nanchang National Invitational

    目录 Contest Info Solutions A. PERFECT NUMBER PROBLEM D. Match Stick Game G. tsy's number H. Coloring ...

  6. P4316 绿豆蛙的归宿 期望DP

    P4316 绿豆蛙的归宿 期望DP DAG上,每条边有边权,走向相连每条路的概率相等,问从起点到终点所经过的路径总长度期望 因为发现终点走到终点期望为0,定义\(f[i]\)从终点走到\(i\)所经过 ...

  7. Poj 2599 Godfather(树的重心)

    Godfather Time Limit: 2000MS Memory Limit: 65536K Description Last years Chicago was full of gangste ...

  8. 在vultr中安装k8s测试

    vultr 安装k8s *** 如果国内访问 k8s.gcr.io 很慢,或者无法访问 *** 在应用yaml文件创建资源时,将文件中镜像地址进行内容替换即可: 将k8s.gcr.io替换为 regi ...

  9. macOs下安装Android SDK

    首先下载 Android SDK for mac 配置安装 1.进入存放 android-sdk-macosx 的目录,然后输入./android sdk就可以调出SDK Manager的图形界面 A ...

  10. spark2.1.0的源码编译

    本文介绍spark2.1.0的源码编译 1.编译环境: Jdk1.8或以上 Hadoop2.7.3 Scala2.10.4 必要条件: Maven 3.3.9或以上(重要) 点这里下载 http:// ...