ES新特性之Proxy对象

ES新特性之Proxy对象,第1张

ES新特性之Proxy对象

大家好,我是一碗周,一个不想被喝(内卷)的前端。如果写的文章有幸可以得到你的青睐,万分有幸~

概述

在ES2015的标准中新增了一个Proxy,用于修改某些 *** 作的默认行为,等同于在语言层面作出的修改,所以说这是属于一种元编程 ,(meta programming),即对编程语言进行编程。

Proxy对象用于创建一个对象的“代理”,从而实现基本能 *** 作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

通俗一点的解释就是,房子比作原始对象,中介比作Proxy,我们租房可以直接找原始房源,也可以通过中介,中介在其中可以屏蔽原始信息。

Proxy的语法结构如下所示:

const p = new Proxy(target, handler)

参数说明:

  • target:要使用Proxy 代理的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

  • handler:这个参数是一个配置对象,对于每一个被代理的 *** 作,都需要提供一个对应的处理函数。

Proxy可拦截的 *** 作

Proxy可拦截的 *** 作如下表所示:

拦截 ⽅法触发⽅式get(target, propKey, receiver)读取某个属性set(target, propKey, value, receiver)写⼊某个属性has(target, propKey)in *** 作符deleteProperty(target, propKey)delete *** 作符getPrototypeOf(target)Object.getPropertypeOf()setPrototypeOf(target, proto)Object.setPrototypeOf()isExtensible(target)Object.isExtensible()preventExtensions(target)Object.preventExtensions()getOwnPropertyDescriptor(target, propKey)Object.getOwnPropertyDescriptor()defineProperty(target, propKey, propDesc)Object.defineProperty()ownKeys(target)Object.keys() 、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()apply(target, thisArg, args)调⽤⼀个函数construct(target, args)⽤ new 调⽤⼀个函数

以上就是Proxy可拦截的所有 *** 作。

Proxy实例的方法

下面我们就对上面那些拦截 *** 作进行逐一演示

get()

get方法用于拦截某个属性的读取 *** 作,该方法可以接受是三个参数,分别是目标对象、被获取的属性名和Proxy实例本身(可选)。

下面是对get的简单用法,如果我们访问一个对象中未定义的属性,可以通过get使其抛出一个异常。

const person = {
    name: '一碗周'
}

const proxy = new Proxy(person, {
    
    get (target, propKey, receiver) {
        if (propKey in target) {
            return target[propKey]
        } else {
            throw new ReferenceError(`属性:${propKey} 不存在`)
        }
    }
})

proxy.name // 一碗周
proxy.hobby // 抛出异常

get方法是可以继承的,看下面这段代码

const person = {
    name: '一碗周'
}

const proxy = new Proxy(person, {
    get (target, properKey, receiver) {
        console.log(`获取${properKey}属性的值:${target[properKey]}`)
        return target[properKey]
    }
})

// 通过proxy创建一个新的对象
const obj = Object.create(proxy)

obj.name // 获取name属性的值:一碗周

上面代码中,拦截 *** 作定义在Prototype对象上面,所以如果读取obj对象继承的属性时,拦截会生效。

我们还可以通过get方法去实现数据读取负数的索引,实现代码如下:

function createArray (...elements) {
    let handler = {
        get (target, properKey, receiver) {
            // 1. 缓存传入的索引值
            let index = Number(properKey)
            if (index < 0) {
                // 例如 target 的长度为7,传递的 index 为 -1, 最后的 properKey 等于 6 即最后一项
                properKey = String(target.length + index)
            }
            
            return Reflect.get(target, properKey, receiver)
        }
    }
    let target = []
    target.push(...elements)
    return new Proxy(target, handler)
}
const arr = createArray(1, 2, 3, 4, 5)

console.log(arr[-1]) // 5

值得注意的是,如果一个属性是不可配置(configurable)且不可写(writable),则Proxy不能修改该属性,否则就会抛出异常。

set()

set方法用于拦截某个对象的修改 *** 作,该方法接受四个参数分别是目标对象、被获取的属性名、修改后的值和Proxy实例本身(可选)。

下面这个例子就规定了修改某个属性必须是某个类型的值,否则就会抛出异常

const person = {
    name: '一碗周'
}

// 1. 根据指定条件修改name属性

const proxy = new Proxy(person, {
    
    set (target, propKey, value, receiver) {
        // 规定修改name属性只能修改为一个字符串,否则就会抛出异常
        if (propKey === 'name' && typeof value !== "string") {
            throw new TypeError('修改的name并不是一个string')
        }
        target[propKey] = value
        return true
    }
})

// proxy.name = 1 // 抛出异常

proxy.name = '一碗周' // 修改成功

我们该可以利用set方法进行数据绑定,如果对象发生改变,就自动更新我们的DOM。

示例代码如下:





  
  
  
  
  通过set自动更新dom



  
    
      
      					
										


					

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5677409.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存