Object.defineProperty基础

作用

定义对象属性的

参数

  1. obj 要定义属性的对象
  2. prop 要定义或修改的属性的名称或 Symbol
  3. descriptor 要定义或修改的属性描述符

特性

默认通过 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
function defineProperty() {
var _obj = {};
Object.defineProperty(_obj, 'a', {
get() {
return 1;
}
})
Object.defineProperties(_obj, {
b: {
value: 2
},
c: {
value: 3
}
})
return _obj;
}

var obj = defineProperty();
console.log(obj.a); // 1
obj.a = 15;
console.log(obj.a); // 不可修改,仍然是 1
for (var key in obj) {
console.log(key + ': ' + obj[key]); // 通过定义的a,b,c默认都不可枚举
}
delete obj.a; // 无法删除a
console.log(obj); // {a:1,b:2,c:3}

writeable可修改、enumerable可枚举、configurable可配置(一般用作可删除)

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
function defineProperty() {
var _obj = {};

Object.defineProperties(_obj, {
a: {
value: 1,
writable: true, // 可修改
enumerable: true, // 可枚举
configurable: true, // 可操作的(一般指删除)
},
b: {
value: 2
}
});
return _obj;
}

const obj = defineProperty();

obj.a = 10;
obj.b = 5;

console.log(obj); // { a: 10, b: 2 }
// a被改了,b没有

for (const key in obj) {
console.log(key + ': ' + obj[key]);
}
// 只打印 a: 10 ,不打印 b

delete obj.a; // 此时可删除a了
console.log(obj); // { b: 2 }

getter/setter

数据劫持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function defineProperty() {
var _obj = {};
var a = 1;
Object.defineProperties(_obj, {
a: {
get() {
return '"a"\'s value is ' + a + '.';
},
set(newVal) {
console.log('The value "a" has been designed a new value "' + newVal + '".');
a = newVal;
}
}
});
return _obj;
}

const obj = defineProperty();
console.log(obj.a); // "a"'s value is 1.
obj.a = 233; // The value "a" has been designed a new value "233".

当给属性设置了 setter、getter 后,不允许设置 value 和 writeable

1
2
3
4
5
6
7
8
9
10
var obj = {};
Object.defineProperty(obj, 'a', {
get() {
return 1;
},
value: 2, // 不可设置
writable: true, // 不可设置
})

// TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>

通过 getter、setter 设置了的属性,在原对象中不可见,但默认可枚举、可删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var obj = {
name: 'Lance',
age: 24
}

var _obj = {};
Object.keys(obj).forEach(key => {
_obj[key] = obj[key];
Object.defineProperty(obj, key, {
get() {
return _obj[key];
},
set(newVal) {
_obj[key] = newVal;
},
});
});

console.log(obj);
for (var key in obj) {
console.log(obj[key]);
}
delete obj.name;
console.log(obj);
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
var obj = {
name: 'Lance',
age: 24
}

var _obj = {};
Object.keys(obj).forEach(key => {
_obj[key] = obj[key];
Object.defineProperty(obj, key, {
// value: 1, // 不可配置
// writeable: false, 不可配置
get() {
return _obj[key];
},
set(newVal) {
_obj[key] = newVal;
},
enumerable: false, // 可配置
configurable : false // 可配置
});
});

console.log(obj);
for (var key in obj) {
console.log(obj[key]);
}
delete obj.name;
console.log(obj);

应用

计算器