js Object.defineProperty() Descriptor features and functions

Object.defineProperty(obj, prop, descriptor)
creates or modifies a property prop on the object obj, and returns the new obj

obj: To define the properties of objects
to be defined or modified: prop Name Symbol attribute or
descriptor: property to define or modify the descriptors
descriptor.configurable: object descriptor properties characteristic

There are two types of attribute descriptors (data descriptors, access descriptors (access descriptors)), and descriptors can only be one of them; when
descriptor is a data descriptor, the attribute is called a data attribute ; for storage When the descriptor is taken, the attribute is called the access attribute ; the
data attribute can be defined by [
object.attribute =value]; the access attribute can only be defined by Object.defineProperty();
the attribute of the descriptor is called the attribute , and the total is [ configurable, enumerable, value, writable, get, set]6, but these 6 cannot coexist;

// [对象.属性 = 值] 方式的 数据描述符 的特性的默认值
descriptor = {
    
    
	configurable: true,
	enumerable: true,
	value: undefined,
	writable: true
}
// defineProperty 方式的 数据描述符 的特性的默认值
descriptor = {
    
    
	configurable: false,
	enumerable: false,
	value: undefined,
	writable: false
}
// 存取描述符 的特性的默认值
descriptor = {
    
    
	configurable: false,
	enumerable: false,
	get: undefined,
	set: undefined
}

Features and conditions of use:

  • configurable, enumerable are public features
  • value, writable are characteristics of data descriptors
  • get, set belong to the characteristics of access descriptor
  • When descriptor has [value, writable], it is data descriptor; when it has [get, set], it is access descriptor
  • When the descriptor is empty, the default is the data descriptor
  • [value, writable] and [get, set] cannot be stored in the same descriptor at the same time, otherwise it will be abnormal

Public optional keys (characteristics):

configurable
If and only when the configurable key value of the attribute is true, the descriptor of the attribute can be changed, and the attribute can also be deleted from the corresponding object.
The default is false.


enumerable
If and only if the enumerable key value of the attribute is true, the attribute will appear in the enumeration attribute of the object.
The default is false.

The data descriptor also has the following optional keys (characteristics):

value
The value corresponding to the attribute. It can be any valid JavaScript value (number, object, function, etc.).
The default is undefined.


writable
If and only if the writable key value of the attribute is true, the value of the attribute, that is, the value above, can be changed by the assignment operator.
The default is false.

The access descriptor also has the following optional keys (characteristics):


The getter function of the get property, if there is no getter, it is undefined. When this property is accessed, this function is called. No parameters are passed in during execution, but the this object is passed in (due to inheritance, this here is not necessarily the object that defines the property). The return value of this function will be used as the value of the attribute.
The default is undefined. The setter function of the


set
property, if there is no setter, it is undefined. When the attribute value is modified, this function will be called. This method accepts a parameter (that is, the new value to be assigned) and will pass in the this object at the time of assignment.
The default is undefined.

See the demo below for details

<html>

<head>
	<title>js Object.defineProperty() 描述符的特性功能详解</title>
</head>

<body>

	<script type="text/javascript">
		"use strict"

		function section1() {
    
    
			let _obj = {
    
    }
			let descriptor = Object.create(null) // 相当于没有 __proto__ 的 {}
			descriptor.value = 1

			// 默认 false, 写不写都一样
			// descriptor.writable = false
			// descriptor.enumerable = false
			// descriptor.configurable = false

			Object.defineProperty(_obj, "val", descriptor);

			console.log("_obj: 对象")
			console.log("\"val\": 对象的属性名")
			console.log("descriptor: 对象的属性的描述符")
			console.log("descriptor.value: 对象的属性的描述符的特性")

		}

		function section2() {
    
    
			let _obj = {
    
    }

			Object.defineProperty(_obj, "val", {
    
    
				value: "val 未修改",
				// writable: false,
				// enumerable: false,
				configurable: false
			});
			Object.defineProperty(_obj, "val2", {
    
    
				value: "val2 未修改",
				// writable: false,
				// enumerable: false,
				configurable: true
			});
			try {
    
    
				Object.defineProperty(_obj, "val", {
    
    
					value: "val 修改",
				});
			} catch (error) {
    
    
				console.warn("[val] configurable: false, 该属性的描述符不可以修改")
			}

			Object.defineProperty(_obj, "val2", {
    
    
				value: "val2 修改",
			});

			try {
    
    
				delete _obj.val
			} catch (error) {
    
    
				console.warn("[val] configurable: false, 该属性不可以被 delete")
			}

			console.log(_obj.val) // val 未修改
			console.log(_obj.val2) // val2 修改

			delete _obj.val2

			console.log(_obj.val2) // undefined
			// val2 被 delete 了

			// 描述符不可以修改指, 除了 writable: true 改 false, [value, writable, configurable, enumerable, get, set] 都不可以修改
			// 前后值相同不算"修改"
		}

		function section3() {
    
    
			let _obj = {
    
    }

			Object.defineProperty(_obj, "val", {
    
    
				value: "val 未修改",
				writable: false,
				// enumerable: false,
				// configurable: false,
			});

			try {
    
    
				_obj.val = "val 修改"
			} catch (error) {
    
    
				console.warn("[val] writable: false, 该属性不能被重新赋值")
			}

			console.log(_obj.val) // val 未修改

		}

		function section4() {
    
    
			let _obj = {
    
    }

			Object.defineProperty(_obj, "val", {
    
    
				value: "val enumerable: false",
				// writable: false,
				enumerable: false,
				// configurable: false,
			});
			Object.defineProperty(_obj, "val2", {
    
    
				value: "val2 enumerable: true",
				// writable: false,
				enumerable: true,
				// configurable: false,
			});

			for (var i in _obj) {
    
    
				console.log(_obj[i]);
			}
			console.log(Object.keys(_obj)) // ["val2"]

			_obj.propertyIsEnumerable("val") // false
			_obj.propertyIsEnumerable("val2") // true

			console.log("[val] enumerable: false, 该属性不能被[for in], Objeck.keys() 等循环方法枚举")

		}

		function section5() {
    
    
			let _obj = {
    
    
				_val: null,
				_val2: null,
			}

			Object.defineProperty(_obj, "val", {
    
    
				get() {
    
    
					console.log("get")
					console.warn("在 get 中调用本属性, 会进入死循环")
					return this._val;
				},
				set(newValue) {
    
    
					console.log("set", newValue)
					this._val = newValue;
				},
				// enumerable: false,
				// configurable: false
			});

			// 赋值触发 set, 新值作为参数传入
			_obj.val = 1

			// 调用触发 get
			_obj.val

		}

		function section6() {
    
    
			let _obj = {
    
    }

			var _val = Object.defineProperty(_obj, "val", {
    
    });

			// 描述符为空时, 默认为数据描述符, { configurable: false, enumerable: false, value: undefined, writable: false }
			console.log(Object.getOwnPropertyDescriptor(_obj, "val"))

			Object.defineProperty(_obj, "val2", {
    
    
				get() {
    
     }
			});

			// get, set 默认为 undefined
			console.log(Object.getOwnPropertyDescriptor(_obj, "val2"))

			_obj.val3 = 3
			// 直接赋值的属性 [configurable, enumerable, writable] 为 true
			console.log(Object.getOwnPropertyDescriptor(_obj, "val3"))

			_obj.__proto__.val4 = 4
			// getOwnPropertyDescriptor 只能取自有属性, 也就是不能取原型链 __proto__ 上的属性
			console.log(Object.getOwnPropertyDescriptor(_obj, "val4"))

		}

		section1()
		section2()
		section3()
		section4()
		section5()
		section6()
	</script>
</body>

</html>



Reference:
Object.defineProperty()-JavaScript | MDN

end

Guess you like

Origin blog.csdn.net/u013970232/article/details/109462642