返回首页

嵌套对象里怎么访问外层属性

重构 caperjs 时绕过 this 链问题的一个记录。

发布 2017年8月09日 标签 #javascript #scope

~/posts/this-chained $ cat post.md

/ 语言 EN / 中文
/ 主题 / /

问题

重构 caperjs 时遇到下面这种结构:

let a = {
    b: 1,
    c: {
        d: function () {
            return this;
        },
        e: function () {
            console.log(b);
        },
    },
};

希望 a.c.d().e() 能拿到 b 的值。dthisc,而 cb 是同级的——要拿到 b,需要先定位到 a。如果 this 能继续追溯一层,那从 cthis 一次回到 a、再 .b(也就是 this.this.b),e 里就能取到值了。

this.this 在 JS 里和 Swift 的 self.self 不一样——它实际等价于 this['this'],而 c 里根本没有 'this' 这个属性。

尝试:用闭包

c 换成函数,在内部把 this 存到一个变量里给子方法用:

let a = {
    b: 1,
    c: function () {
        let that = this;
        return {
            d: function () {
                return this;
            },
            e: function () {
                console.log(that.b);
            },
        };
    },
};

但这样调用方就变成了 a.c().d().e()——多了一对括号,和原本的 a.c.d().e() 不一样。

现在再看

问题其实不在 this,而在 e 里引用的 b——它根本不在作用域里,必然报 ReferenceError。给它一个能找到的名字就行:

let a = {
    b: 1,
    c: {
        d() {
            return this;
        },
        e() {
            console.log(a.b);
        },
    },
};

a.c.d().e(); // 1

e 是后面被调用的,那时 a 已经绑定完成,直接按名字引用就好。整件事不需要 this 链,也不必把 c 变成函数——只要把对外层的依赖明写出来。

返回首页