[[HomeObject]] 到底是啥新奇玩意? --<Javascript 学习笔记 2>

Lemon1x
• 阅读 130

Javascript 学习笔记 2

本文整理自现代 Javascript 教程

在 JS 的 class 中,继承类要用 super 进行访问父类,如果我们从原理上剖析,我们可以得到如下代码:

const Base = {
    name: 'Base',

    show() {
        console.log(`Hello ${this.name}!`);
    }
};

const Sub = {
    __proto__: Base,
    name: 'Sub',

    show() {
        this.__proto__.show();
    }
};

Sub.show(); // Hello Base!

然而结果很不理想,返回的竟然是 Base 而不是 Sub,那为什么呢?因为JS的 this 是自由的,它由词法环境决定,因为此时的 show 在 Base 里执行,但我们有很多改变 this 指向的方法,比如 call

const Sub = {
    __proto__: Base,
    name: 'Sub',

    show() {
        this.__proto__.show.call(this);
    }
};

Sub.show(); // Hello Sub!

这时正确的返回了Sub,可是这时我们又想继承一个对象:

const Other = {
    __proto__: Sub,
    name: 'Other',

    show() {
        this.__proto__.show.call(this);
    }
};

Other.show(); // RangeError: Maximum call stack size exceeded

什么东西?竟然报错了,其实仔细想一想就知道,这时 Other 的 this 是自己,也就是Other.proto.show.call(Other) ,再往下传递,到了 Sub 的 show 方法,因为有了 call ,this 还是 Other,于是就陷入了无限的递归中。

咋解决呢,这时就用到了 super 关键词:

const Sub = {
    __proto__: Base,
    name: 'Sub',

    show() {
        super.show();
    }
};

const Other = {
    __proto__: Sub,
    name: 'Other',

    show() {
        super.show();
    }
};

Other.show(); // Hello Other!

终于可以正确输出了!那么这时怎么做到的呢?实际上 super 用到了一个内部隐藏属性 [[HomeObject]],它指向本对象,实际上它把代码变成了这个样子:

const Sub = {
    __proto__: Base,
    name: 'Sub',

    show() { // Sub.show.[[HomeObject]] = Sub
        Sub.__proto__.show.call(Other);
    }
};

const Other = {
    __proto__: Sub,
    name: 'Other',

    show() { // Other.show.[[HomeObject]] = Other
        Other.__proto__.show.call(Other);
    }
};

[[HomeObject]]只是让JS从父类原型中获取方法,this 指向不变。

评论区
推荐文章

暂无数据

Lemon1x
Lemon1x
Lv1
学生
初二的某个班长,目前为JS开发者。 知乎同名,Gitee: Lemonix,Github: Lemonix-xxx
0
文章
0
粉丝
0
获赞
热门文章

暂无数据