首页 > 其他分享 >兼收并蓄 TypeScript - 进阶: proxy, reflect

兼收并蓄 TypeScript - 进阶: proxy, reflect

时间:2024-09-20 12:25:43浏览次数:11  
标签:Reflect TypeScript 进阶 Object reflect propertyKey proxy let target

源码 https://github.com/webabcd/TypeScriptDemo
作者 webabcd

兼收并蓄 TypeScript - 进阶: proxy, reflect

示例如下:

advanced\proxy_reflect.ts

{
    // Proxy - 代理(拦截目标对象的属性操作和函数操作)
    let target = {
        name: 'webabcd',
        age: 40,
        get hello() {
            return this.name + this.age;
        }
    }
    let handler = {
        get: function(target:any, propertyKey:string, receiver:any) { // receiver 就是 Proxy 实例本身
            console.log("get: "+ propertyKey);
            return target[propertyKey];
        },
        set: function(target:any, propertyKey:string, value:any, receiver:any) { // receiver 就是 Proxy 实例本身
            console.log("set: " + propertyKey);
            target[propertyKey] = value;
            return true; // 对于 handler 的 set() 来说,必须要有 return true
        },
        has: function(target:any, propertyKey:string){
            console.log("has: " + propertyKey);
            return propertyKey in target;
        }
        /*
         * 其他可代理的方法如下:
         * construct() - 执行 new Proxy() 时
         * getPrototypeOf() - 执行 Object.getPrototypeOf(proxy) 时
         * setPrototypeOf() - 执行 Object.setPrototypeOf(proxy) 时
         * preventExtensions() - 执行 Object.preventExtensions(proxy) 时
         * isExtensible() - 执行 Object.isExtensible(proxy) 时
         * defineProperty() - 执行 Object.defineProperty(proxy) 时
         * ownKeys() - 执行 Object.getOwnPropertyNames(proxy) 时
         * deleteProperty() - 执行 delete proxy.prop 时
         */
    }
    // Proxy - 让 handler 处理 target 的属性和方法
    let proxy = new Proxy(target, handler);
    proxy.name = "wanglei"; // 会走到 handler 的 set()
    let name = proxy.name; // 会走到 handler 的 get()
    let exists = ("name" in proxy); // 会走到 handler 的 has()


    // 通过 handler 的 apply() 代理函数的调用
    function target2(a:number, b:number) {
        return a + b;
    }
    let handler2 = {
        apply: function(target:any, ctx:any, args:any[]) {
            console.log("apply: " + args.join(","));
            return target(...args);
        }
    };
    let proxy2 = new Proxy(target2, handler2);
    console.log(proxy2(100, 50)); // 150


    // 通过 handler 的 construct() 代理构造函数
    class Target3 {  
        constructor(public a: number, public b: number) {  

        }  
        hello(): number {  
            return this.a + this.b;  
        }  
    }  
    let handler3 = {
        construct(target:any, argArray:any[]) {
            console.log("construct: "+argArray.join(","));
            return new target(...argArray);
        }
    };
    let proxy3 = new Proxy(Target3, handler3);
    console.log(new proxy3(100, 50).hello()); // 150




    // Reflect - 反射
    let target4 = {
        name: 'webabcd',
        age: 40,
        get hello() {
            return this.name + this.age;
        }
    }
    // Reflect.get() - 获取指定对象的指定属性
    console.log(Reflect.get(target4, "hello")); // wanglei40
    // Reflect.get() - 获取指定对象的指定属性(对象中的 this 会指向 Reflect.get() 的第 3 个参数)
    console.log(Reflect.get(target4, "hello", {name: "xyz"})); // xyzundefined
    // Reflect.set() - 设置指定对象的指定属性
    Reflect.set(target4, 'name', "abc");
    console.log(Reflect.get(target4, "name")); // abc


    class Target5 {  
        constructor(public a: number, public b: number) {  

        }  
        hello(p:string): string {  
            return `${p} ${this.a + this.b}`;
        }  
    }  
    // Reflect.apply() - 调用指定的函数
    //     第 1 个参数:目标函数
    //     第 2 个参数:目标函数的 this 指向的对象
    //     第 3 个参数:传入目标函数的参数列表
    let t5 = new Target5(1, 2);
    console.log(Reflect.apply(t5.hello, {a:100, b:200}, ['xxx'])); // xxx 300
    

    class Target6 {  
        constructor(public a: number, public b: number) {  

        }  
        hello(): number {  
            return this.a + this.b;  
        }  
    }  
    // Reflect.construct() - 调用构造函数并传参
    let t6 = Reflect.construct(Target6, [100, 200]);
    console.log(t6.hello()); // 300


    /*
     * 关于 Reflect 除了上面说的,还有如下:
     * 注:这些都可以在 Object 中找到相同的用法,可以参见 class/prototype.js 中的关于 Object 的相关说明以及 basic/object.js 中的关于 Object 的相关的说明
     * defineProperty() - 类似 Object.defineProperty()
     * deleteProperty() - 类似 delete obj.prop
     * getPrototypeOf() - 类似 Object.getPrototypeOf()
     * setPrototypeOf() - 类似 Object.setPrototypeOf()
     * preventExtensions() - 类似 Object.preventExtensions()
     * isExtensible() - 类似 Object.isExtensible()
     * ownKeys() - 类似 Object.getOwnPropertyNames()
     *
     * 注:能用 Reflect 的方法就用 Reflect 的,而不要再用 Object 的了
     */




    // 通过 Proxy 和 Reflect 实现察者模式
    let myObj = {
        name: 'webabcd'
    }
    let myHandler = {
        set: function(target:any, propertyKey:string, value:string, receiver:any) {
            const result = Reflect.set(target, propertyKey, value, receiver);
            observerList.forEach(observer => observer(propertyKey, value));
            return result;
        }
    }
    const observerList: Function[] = [];
    const observer = (fn:Function) => observerList.push(fn);
    const observable = (obj:any) => new Proxy(obj, myHandler);

    // 指定观察者
    observer((propertyKey:string, value:string) => {
        console.log(`我是观察者 1,发现 myObj 的 ${propertyKey} 的值变为了 ${value}`);
    });
    observer((propertyKey:string, value:string) => {
        console.log(`我是观察者 2,发现 myObj 的 ${propertyKey} 的值变为了 ${value}`);
    });

    // 指定可被观察的对象,属性发生变化时通知所有观察者
    let observableObj = observable(myObj);
    observableObj.name = "wanglei";
}

源码 https://github.com/webabcd/TypeScriptDemo
作者 webabcd

标签:Reflect,TypeScript,进阶,Object,reflect,propertyKey,proxy,let,target
From: https://www.cnblogs.com/webabcd/p/18422277/typescript_advanced_proxy_reflect

相关文章

  • 兼收并蓄 TypeScript - 第三方库: 类型声明
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-第三方库:类型声明示例如下:third\typeDeclaration.ts/**类型声明用于TypeScript调用JavaScript*类型声明定义在.d.ts声明文件中*比如aes.js文件,其对应的声明文件为ae......
  • 兼收并蓄 TypeScript - 第三方库: crypto-js
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-第三方库:crypto-js示例如下:third\cryptojs.ts/**本例以在TypeScript中使用crypto-js为例*crypto-js是一个纯js项目,是不能直接在typescript中使用的,需要相应的.d.ts......
  • 兼收并蓄 TypeScript - 基础: number
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:number示例如下:basic\number.ts{//将指定类型的数据转换为number类型console.log(Number("100"),Number(true),Number({}),Number([]));//1001NaN0//......
  • 兼收并蓄 TypeScript - 基础: string
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:string示例如下:basic\string.ts{leta="\x7A";//十六进制的“7A”是字符“z”letb="\u{7A}";//十六进制的“7A”是字符“z”letc="\u{738B}";......
  • 兼收并蓄 TypeScript - 基础: symbol
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:symbol示例如下:basic\symbol.ts{//Symbol()是一个全局函数,返回一个唯一的Symbol值consta=Symbol();constb=Symbol();//b与a不同constc=Sy......
  • 兼收并蓄 TypeScript - 基础: array
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:array示例如下:basic\array.ts{//array-数组//创建数组letarray1:number[]=[1,2,3];letarray2:Array<number>=[1,2,3];letarray3:Ar......
  • 兼收并蓄 TypeScript - 基础: set
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:set示例如下:basic\set.ts{//set是一个集合,先进先出,不会插入重复数据,数据支持类型的多样性//常规操作有add(),delete(),has(),clear(),size等letmySet=......
  • 兼收并蓄 TypeScript - 基础: map
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:map示例如下:basic\map.ts{//map是一个key/value集合,先进先出,遇到重复键值则后面的会覆盖前面的,key和value都支持类型的多样性//常规操作有set(),get(),dele......
  • 兼收并蓄 TypeScript - 基础: tuple
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-基础:tuple示例如下:basic\tuple.ts{//tuple-元组leta:[string,number]=['webabcd',22];a[0]='wanglei';a[1]=44;console.log(a,a[0......
  • 兼收并蓄 TypeScript - 类: enum
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-类:enum示例如下:class\enum.ts{//简单枚举enumStatus{ok,error};console.log(Status["ok"],Status["error"]);//01console.log(Status[0],Status......