Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defineProperty & Proxy 对于代理数组出现的差异 #32

Open
semi-xi opened this issue Mar 1, 2021 · 0 comments
Open

defineProperty & Proxy 对于代理数组出现的差异 #32

semi-xi opened this issue Mar 1, 2021 · 0 comments

Comments

@semi-xi
Copy link
Owner

semi-xi commented Mar 1, 2021

definePropertity

!数据描述符与存取描述符只能2选其1
数据描述符: value,writable
存取描述符: get, set

const obj = {}
Object.defineProperty(obj, 'a', {
  configurable: true,
  enumerable: true,
  get:() => {
    console.log('get')
    return val;
  },
  set: (newVal) => {
    console.log('set')
    val = newVal
  }

})

obj.a = [] // set
obj.a.push('1') // get
obj.a[0] = 1 // get
obj.a.pop(1) // get
obj.a = [1, 2, 3] // set

当使用数组自身的一些方法如push、pop等为数组添加或删除元素时,不能触发属性a的setter,无法实现对属性a中元素的实时监听
值得注意的是上面使用push、pop、直接通过索引为数组添加元素时会触发属性a的getter,是因为与这些操作的返回值有关,以push方法为例,使用push方法为数组添加元素时,push方法返回值是添加之后数组的新长度,当访问数组新长度时就会自然而然触发属性a的getter

proxy

let arr = []
let arrProxy = new Proxy(arr, {
  get: (target, prop) => {
    console.log('get value by proxy')
    return prop in target ? target[prop] : undefined
  },
  set: (target, prop, value) => {
    console.log('set value by proxy', target, prop, value)
    target[prop] = value
    return true
  }
})

arrProxy.push(1)
// get value by proxy  // 获取数组arr的push方法
// get value by proxy  // 获取数组arr的length属性
// set value by proxy  // 设置arr[0] = 1
// set value by proxy  // 设置数组arr长度为1

使用proxy代理数组时,调用数组的push方法可以触发一系列操作,具体如下:触发数组的getter,获取数组arr的push方法;触发数组的getter,获取arr的length属性;触发数组的setter,设置arr[0] = 1;触发数组的setter,设置数组arr的长度为1;直接使用索引值进行添加改变元素时也会触发数组arr的setter

额外联想:

function Hello() {
    let hello = 'hello world';
    Object.defineProperty(this, 'hello', {
        get(){
            console.log('get');
            return hello;
        },
        set(value){
            console.log('set');
            hello = value;
        }
    })
}
 
let obj = new Hello();
console.log(obj.hello);
obj.hello = 'goodbye';
console.log(obj.hello); 

参考

大前端训练营 - 模块1.2:Proxy和definedProperty对比

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant