The Object.defineProperty()
method directly defines a new property on an object or modifies an existing property of an object, and returns the object. In other words, this method allows precise addition or modification of object properties.
Object.defineProperty(obj, prop, descriptor)
obj
: The object on which to define the property.
prop
: The name of the property to be defined or modified, or a Symbol
.
descriptor
: The property descriptor to be defined or modified.
There are two main forms of property descriptors in an object: data descriptors and accessor descriptors. A data descriptor is a property with a value, which can be writable or non-writable. An accessor descriptor is a property described by getter
and setter
functions. A descriptor can only be one of either a data descriptor or an accessor descriptor, it cannot be both at the same time.
Property Descriptor | configurable | enumerable | value | writable | get | set |
---|---|---|---|---|---|---|
Data Descriptor | Yes | Yes | Yes | Yes | No | No |
Accessor Descriptor | Yes | Yes | No | No | Yes | Yes |
If a descriptor does not have any of the keys value
, writable
, get
, or set
, then it will be considered as a data descriptor. If a descriptor has both value
or writable
and get
or set
keys, an exception will be thrown.
In addition, these options may not necessarily be own properties, inherited properties should also be considered. To confirm the retention of these default values, it may be necessary to freeze Object.prototype
before setting, explicitly specify all options, or use Object.create(null)
to set the __proto__
property to null
.
The property descriptor for a property can only be changed if the configurable
key value is true
, and the property can be deleted from the corresponding object as well, defaulting to false
when defining a property using Object.defineProperty()
.
"use strict";
// In non-strict mode, silent failure occurs, no error is thrown, and there is no effect
// In strict mode, a failure will result in an exception being thrown
var obj = {};
Object.defineProperty(obj, "key", {
configurable: true,
value: 1
});
console.log(obj.key); // 1
Object.defineProperty(obj, "key", {
enumerable: true // Descriptors can be changed when configurable is true
});
delete obj.key; // Property can be deleted when configurable is true
console.log(obj.key); // undefined
"use strict";
var obj = {};
Object.defineProperty(obj, "key", {
configurable: false,
value: 1
});
console.log(obj.key); // 1
Object.defineProperty(obj, "key", {
enumerable: true // Descriptors cannot be changed when configurable is false // Uncaught TypeError: Cannot redefine property: key
});
delete obj.key; // Property cannot be deleted when configurable is false // Uncaught TypeError: Cannot delete property 'key' of #<Object>
console.log(obj.key); // undefined
A property will only appear in the object's enumerable properties if the enumerable
key value is true
, defaulting to false
.
"use strict";
var obj = { a: 1 };
Object.defineProperty(obj, "key", {
enumerable: true,
value: 1
});
for(let item in obj) console.log(item, obj[item]);
/*
a 1
key 1
*/
"use strict";
var obj = { a: 1 };
Object.defineProperty(obj, "key", {
enumerable: false,
value: 1
});
for(let item in obj) console.log(item, obj[item]);
/*
a 1
*/
The value corresponding to this property can be any valid JavaScript
value, and its default is undefined
.
"use strict";
var obj = {};
Object.defineProperty(obj, "key", {
value: 1
});
console.log(obj.key); // 1
"use strict";
var obj = {};
Object.defineProperty(obj, "key", {});
console.log(obj.key); // undefined
The value of this property can only be changed by the assignment operator if the writable
key is set to true
, and its default is false
.
"use strict";
var obj = {};
Object.defineProperty(obj, "key", {
value: 1,
writable: true
});
console.log(obj.key); // 1
obj.key = 11;
console.log(obj.key); // 11
"use strict";
var obj = {};
Object.defineProperty(obj, "key", {
value: 1,
writable: false,
configurable: true
});
console.log(obj.key); // 1
obj.key = 11; // Uncaught TypeError: Cannot assign to read only property 'key' of object '#<Object>'
Object.defineProperty(obj, "key", {
value: 11 // It's possible to change the value through redefinition, but remember that configurable needs to be true
});
console.log(obj.key); // 11
The property's getter
function, if not defined, is undefined
. When accessing this property, this function is called, and it does not take any parameters at execution, but the this
object is passed in. Due to inheritance, this
may not necessarily refer to the object defining this property. The return value of this function is used as the property's value, and its default is undefined
.
"use strict";
var obj = { __x: 1 };
Object.defineProperty(obj, "x", {
get: function(){ return this.__x; }
});
console.log(obj.x); // 1
"use strict";
var obj = { __x: 1 };
Object.defineProperty(obj, "x", {
get: function(){ return this.__x; }
});
console.log(obj.x); // 1
obj.x = 11; // Cannot directly assign a value without a set method // Uncaught TypeError: Cannot set property x of #<Object> which has only a getter
The property's setter
function, if not defined, is undefined
. This function is called when the property value is modified. It receives a parameter and the this
object at the time of assignment, enabling the assignment operation, and its default is undefined
.
"use strict";
var obj = { __x: 1 };
Object.defineProperty(obj, "x", {
set: function(x){ this.__x = x; },
get: function(){ return this.__x; }
});
obj.x = 11;
console.log(obj.x); // 11
"use strict";
var obj = { __x: 1 };
Object.defineProperty(obj, "x", {
set: function(x){
console.log("Operations can be performed before assignment");
this.__x = x;
}
});
obj.x = 11;
Strict mode in JavaScript: link Object traversal in JavaScript: link
https://github.com/WindrunnerMax/EveryDay
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty