class 类 this指向的问题

摘要:ES6中的 class定义一个类, 其内部包含 constructor构造函数, 除了在构造函数显示的定义一些属性, 其余的默认都添加到这个类的原型对象上。以上代码 classProxy(prosen2) 返回的是包含一层拦截器的实例对象, 当读取 sayName这个函数的是和会出发 get拦截等操作。

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

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_1715