class 类 this指向的问题

ES6 实现了类的概念

    class Prosen {
        
    }

ES5使用函数模拟

    function Prosen() {
        
    }

ES6中的 class定义一个类, 其内部包含 constructor构造函数, 除了在构造函数显示的定义一些属性, 其余的默认都添加到这个类的原型对象上。

在一个类中定义一个读取名字的函数:

    class Prosen {
        constructor(name) {
            this.name = name;
        }
        sayName() {
            console.log(this.name)
        }
    }
    
    const prosen = new Prosen('zhangsan')
    prosen.sayName()  //张三

如果我们把 sayName 这个函数拿出来运行会是什么结果呢?

继以上代码

    const prosen1 = new Prosen('lisi')
    const { sayName } = prosen1
    sayName()  // 报错

以上报错的原因是 sayName函数中的 this不对。指向的不是 prosen1这个实例对象,所以是无法读取name 属性的。

使用 proxy来代理实例对象,拦截读取操作并修改this的指向

    function classProxy(target) {
        const m = WeakMap()
        // 读取拦截配置, 只需要配置 get
        const hanlder = {
            get(target, key) {
                const val = Reflect.get(target, key)
                // 要获取的是函数执行, 如果不是函数就直接返回 val
                if (typeof val !== 'function') return val
                if (!m.has(val)) {
                    // 使用 bind改变运行函数的 this为拦截的实例对象
                    m.set(val, val.bind(target))
                }
                return m.get(val)
            }
        }
        const proxy = new Proxy(target, hanlder)
        return proxy
    }

继以上代码

    const prosen2 = new Prosen('qiqingfu')
    const { sayName } = classProxy(prosen2)
    sayName()  // qiqingfu

以上代码 classProxy(prosen2) 返回的是包含一层拦截器的实例对象, 当读取 sayName这个函数的是和会出发 get拦截等操作。

总结其它知识点

proxy: 拦截器, 用于对象操作的自定义行为(如属性查找, 赋值, 枚举, 函数调用, 是实例化等)

Reflect 是一个内置的对象, 它提供拦截 Javascript方法,和Object操作类似。

WeakMap: 可以实现对象 值-值的对应, 并且一个对象的键值只能是对象,且不计入垃圾回收机制,可对象引用常驻内存造成的内存泄漏等问题。

WeakMap:

    const n = {a: 1}
    const m = new WeakMap()
    m.set(n, 1)
    m.get(n) // 1
    m.has(n) // true

猜你喜欢

转载自www.cnblogs.com/qiqingfu/p/10193254.html