defineProperty 的用法详解

语法

1
Object.defineProperty(obj, prop, descriptor);

参数

  • obj:要在其上定义属性的对象。
  • prop:要定义或修改的属性的名称。
  • descriptor:正在定义或修改的属性的描述符。
  • 返回值 传递给函数的对象

添加属性和默认值

1
2
3
4
5
6
7
8
9
var o = {}; // 创建一个新对象

Object.defineProperty(o, "a", {
**proto**: null,
value : 1,
writable : true,
enumerable : true,
configurable : true
});

设置和修改属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var bValue;

Object.defineProperty(o, "b", {
get: function () {
return bValue;
},
set: function (newValue) {
bValue = newValue;
},

enumerable: true,
configurable: true
});
o.b = 18;

视图控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<div>
<p>
你好,
<span id="nickName"></span>
</p>
<div id="introduce"></div>
</div>
 
<script>
//视图控制器
var userInfo = {};
Object.defineProperty(userInfo, "nickName", {
get: function () {
return document.getElementById("nickName").innerHTML;
},
set: function (nick) {
document.getElementById("nickName").innerHTML = nick;
}
});

Object.defineProperty(userInfo, "introduce", {
get: function () {
return document.getElementById("introduce").innerHTML;
},
set: function (introduce) {
document.getElementById("introduce").innerHTML = introduce;
}
});

//数据
//todo 获取用户信息的代码

userInfo.nickName = "张无忌";
userInfo.introduce = "九阳神功护体";
</script>

Object.defineProperty 实现简单的双向绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style type="text/css">
.box {
width: 200px;
background-color: skyblue;
}
img {
display: block;
}
</style>
</head>
<body>
<input type="text" id="btn" />
<p></p>

<script type="text/javascript">
let obj = {};
let temp = {};
document.getElementById("btn").onkeyup = function () {
obj.name = document.getElementById("btn").value;
};
Object.defineProperty(obj, "name", {
get() {
return 1;
},
set(val) {
temp["name"] = val;
document.querySelector("p").innerHTML = temp["name"];
}
});
</script>
</body>
</html>

Proxy 与 Object.defineProperty 优劣对比

  • Proxy 的优势如下:

    1. Proxy 可以直接监听对象而非属性;
    2. Proxy 可以直接监听数组的变化;
    3. Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
    4. Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
    5. Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
  • Object.defineProperty 的优势如下:
    兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。