我们都知道Vue2中的响应式原理使用了Object.defineProperty
, 那么你知道Object.defineProperty
的一些使用细节吗!在面试过程中遇到这些细节考察,你是否可以轻松面对呢!今天我们就来探索一下Object.defineProperty使用的4个细节点。
一、 Object.defineProperty定义对象的默认行为
面试官:请说出下面代码的输出结果。
js
function test1() {
var a = {};
var obj = Object.defineProperty(a, "b", {
value: 1,
});
return obj;
}
var obj1 = test1();
console.log("结果1:", obj1);
obj1.b = 2;
console.log("结果2:", obj1);
obj1.c = 3;
for (var key in obj1) {
console.log("结果3:", obj1[key]);
}
delete obj1.b;
console.log("结果4:", obj1);
答案如下:

对于结果1相信大家都觉得正常,不用思考就能写出答案,但是结果2、3、4,就需要你对Object.defineProperty的默认行为有所掌握了。结果2、3、4证明了Object.defineProperty 的3个默认行为:
- Object.defineProperty 定义的属性默认不可以修改
- Object.defineProperty 定义的属性默认不可枚举
- Object.defineProperty 定义的属性默认不能删除
那么如何才能将Object.defineProperty 定义的属性变成可以修改,可以枚举和可以删除的呢?这时需要在定义时添加 writable,enumerable, configurable 3个配置。具体使用如下:
js
function test1() {
var a = {};
var obj = Object.defineProperty(a, "b", {
value: 1,
writable: true, // 定义是否可写,也就是否可以修改
enumerable: true, // 定义是否可以枚举
configurable: true, // 定义是否可以删除
});
return obj;
}
var obj1 = test1();
console.log("结果1:", obj1);
obj1.b = 2;
console.log("结果2:", obj1);
obj1.c = 3;
for (var key in obj1) {
console.log("结果3:", obj1[key]);
}
delete obj1.b;
console.log("结果4:", obj1);
输出结果如下:

二、Object.defineProperty 中getter setter方法的使用
面试官:请用Object.defineProperty
写一个简单的响应式
分析: 其实这主要就是考察你是否知道Object.defineProperty
中的getter setter方法的用法, 实现方式如下:
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>响应简单实现</title>
</head>
<body>
<div>
<button id="btn">加一</button>
<p>result:<span id="result">0</span></p>
</div>
<script>
function reactive() {
var obj = {};
var result = 0;
var obj2 = Object.defineProperty(obj, "result", {
get: function (value) {
return result;
},
set: function (newVal) {
console.log(newVal);
result++;
document.getElementById("result").innerHTML = newVal;
},
});
return obj;
}
var obj = reactive();
document.getElementById("btn").onclick = function () {
obj.result++;
};
</script>
</body>
</html>
当点击按钮加一的时候,你会看到页面的result 更新来了,而在点击事件里面我们并没有去操作dom,这其实就是Vue2实现响应式的底层核心原理,只是Vue2中封装得更完善,可配置性更高。
三、Object.defineProperty 中, value 和getter setter 方法的互斥性
面试官: 请问下面代码会输出什么
js
function test() {
var obj = {};
Object.defineProperty(obj, "b", {
value: 1,
get: function () {
return 5;
},
set: function (newVal) {},
});
return obj;
}
var newObj = test();
console.log(newObj);
答案是什么也不会输出,会直接报错:

这里其实不只是get setter 和value 不能共存,getter setter 和writable, enumerable 也不能共存,只有getter setter 和getter setter 一起的时候不会报错
四、 Object.defineProperties
面试官: 请问Object.defineProperty
可以同时定义多个属性吗?可以的话怎么定义,不可以的话有其他解决方案吗?
答案是Object.defineProperty
不可以同时定义多个属性,可以使用Object.defineProperties
来解决。具体使用方式如下:
js
function test() {
var obj = {};
Object.defineProperties(obj, {
a: {
value: 1,
writable: true,
enumerable: true,
configurable: true,
},
b: {
value: 2,
},
});
return obj;
}
var newObj = test();
console.log(newObj);
总结
本篇通过4个面试题来加深对Object.defineProperty 的理解,希望看了本篇遇到类似的面试题能够顺利通过,,感谢收看