欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

class 类 this指向的问题

程序员文章站 2022-09-04 14:59:32
ES6 实现了类的概念 ES5使用函数模拟 ES6中的 class定义一个类, 其内部包含 构造函数, 除了在构造函数显示的定义一些属性, 其余的默认都添加到这个类的原型对象上。 在一个类中定义一个读取名字的函数: 如果我们把 sayName 这个函数拿出来运行会是什么结果呢? 继以上代码 以上报错 ......

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