Appearance
Object.defineProperty
在一个对象上定义新的属性或修改现有属性,并返回该对象
- obj:要定义属性的目标对象
- prop:要定义或修改的属性的名称
- descriptor:属性的描述符对象
- value:属性值
- writable:属性值是否可修改
- enumerable:是否可枚举
- configurable:是否可被删除
- get:该属性的 getter 函数,用于返回属性的值。如果定义了 get,则该属性会变成一个访问器属
- set:该属性的 setter 函数,用于设置属性的值。如果定义了 set,则该属性会变成一个访问器属性
定义单一属性
js
function defineProperty() {
var _obj = {}
// 定义单一属性
Object.defineProperty(_obj, 'a', {
value: 1
})
return _obj
}
var obj = defineProperty()
console.log('🚀 ~ obj:', obj)
定义多属性
js
function defineProperty() {
var _obj = {}
// 定义多属性
Object.defineProperties(_obj, {
a: {
value: 1
},
b: {
value: 2
},
c: {
value: 3
}
})
return _obj
}
var obj = defineProperty()
console.log('🚀 ~ obj:', obj)
此时obj不可修改、不可枚举、不可删除,因为没有配置descriptor
可进行删除、修改、枚举的配置
js
function defineProperty() {
var _obj = {}
// 定义多属性
Object.defineProperties(_obj, {
a: {
value: 1,
writable: true,
enumerable: true,
configurable: true
},
b: {
value: 2
},
c: {
value: 3
}
})
return _obj
}
var obj = defineProperty()
obj.a = 5
delete obj.a
console.log('🚀 ~ obj:', obj)
get与set
js
const obj = {}
let _name = 'Alice'
Object.defineProperty(obj, 'name', {
get: function () {
return _name
},
set: function (newName) {
_name = newName
},
enumerable: true,
configurable: true
})
console.log(obj.name) // "Alice"
obj.name = 'Bob'
console.log(obj.name) // "Bob"
数据劫持:阻拦正常的输出和输入,对descriptor进行一系列配置,按照get和set里的逻辑进行数据操作的逻辑,这就叫做数据劫持
尝试对数组进行数据劫持
js
function DataArr() {
var _val = null,
_arr = []
Object.defineProperty(this, 'val', {
get: function () {
return _val
},
set: function (newVal) {
_val = newVal
_arr.push({ val: _val })
console.log(`new value${_val}`)
}
})
this.getArr = function () {
return _arr
}
}
var dataArr = new DataArr()
dataArr.val = 123
dataArr.val = 234
console.log('🚀 ~ dataArr:', dataArr)
Proxy
ES6的一个构造函数,用于创建一个对象的代理,从而实现基本操作的拦截和自定义
- target:原始对象
- handler:定义拦截行为的对象,包含多个陷阱方法
- get(target, prop, receiver):拦截对象属性的读取。
- set(target, prop, value, receiver):拦截对象属性的设置。
- has(target, prop):拦截 in 操作符。
- deleteProperty(target, prop):拦截删除属性的操作。
- apply(target, thisArg, argumentsList):拦截函数调用。
- construct(target, argumentsList, newTarget):拦截构造函数的调用。
Object.defineProperty与Proxy主要区别
defineProperty是直接处理obj,并且在set和get去拦截
proxy是处理了obj后返回了一个代理对象
简单用法
js
var target = {
a: 1,
b: 2
}
let proxy = new Proxy(target, {
get(target, propKey) {
console.log(`tar:${target},propKey:${propKey},value:${target[propKey]}`)
return target[propKey]
},
set(target, propKey, value) {
target[propKey] = value
}
})
console.log('🚀 ~ proxy:', proxy.a)