gpt4 book ai didi

javascript - 与 'super' 相比,如何确定 'this' 的值?

转载 作者:行者123 更新时间:2023-12-03 07:07:49 26 4
gpt4 key购买 nike

this由执行上下文决定

我习惯了this的特点在 JavaScript 中。在以下示例中,this由执行上下文决定。尽管getProtoPropViaThis函数在 x 上定义, this 的值由函数的调用方式决定:

const xProto = {
protoProp: "x",
};

const x = {
getProtoPropViaThis() {
return this.protoProp;
},
}
Object.setPrototypeOf(x, xProto);

const yProto = {
protoProp: "y",
};

const y = {
getProtoPropViaThis: x.getProtoPropViaThis,
}
Object.setPrototypeOf(y, yProto);

console.log( x.getProtoPropViaThis() ); // Output: x
console.log( y.getProtoPropViaThis() ); // Output: y

super不受执行上下文影响?

我一直在使用 super现在有一段时间了,但总是在类里面。所以我最近读到an article时感到很惊讶。切线地证明了super似乎不遵循与 this 相同的规则.不知何故,在某种程度上我不完全理解(尽管多次阅读 ECMAScript 2021 language docs),super设法保留其原始引用资料:

const xProto = {
protoProp: "x",
};

const x = {
getProtoPropViaSuper() {
return super.protoProp;
},
}
Object.setPrototypeOf(x, xProto);

const yProto = {
protoProp: "y",
};

const y = {
getProtoPropViaSuper: x.getProtoPropViaSuper,
}
Object.setPrototypeOf(y, yProto);

console.log( x.getProtoPropViaSuper() ); // Output: x
console.log( y.getProtoPropViaSuper() ); // Output: x

请注意 y没有 xxProto在其原型(prototype)链中的任何位置,但它仍然是 xProto调用 y.getProtoPropViaSuper() 时访问的属性

明显的差异 Object.assign

再举个例子,下面的根本不起作用:

const xProto = {
protoProp: "x",
};

const x = Object.assign(Object.create(xProto), {
getProtoPropViaSuper() {
return super.protoProp;
},
});

console.log(x.getProtoPropViaSuper());

super 的值是对象的原型(prototype),不是x的,所以上面的例子只打印了 undefined .

遵循文档

12.3.7.1 Runtime Semantics: Evaluation

SuperProperty :super. IdentifierName

  1. Let env be GetThisEnvironment().
  2. Let actualThis be ? env.GetThisBinding().
  3. Let propertyKey be StringValue of IdentifierName.
  4. If the code matched by this SuperProperty is strict mode code, let strict be true; else let strict be false.
  5. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict).

12.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

The abstract operation MakeSuperPropertyReference takes arguments actualThis, propertyKey, and strict. It performs the following steps when called:

  1. Let env be GetThisEnvironment().
  2. Assert: env.HasSuperBinding() is true.
  3. Let baseValue be ? env.GetSuperBase().
  4. Let bv be ? RequireObjectCoercible(baseValue).
  5. Return a value of type Reference that is a Super Reference whose base value component is bv, whose referenced name component is propertyKey, whose thisValue component is actualThis, and whose strict reference flag is strict.

8.1.1.3.5 GetSuperBase ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. Let home be envRec.[[HomeObject]].
  3. If home has the value undefined, return undefined.
  4. Assert: Type(home) is Object.
  5. Return ? home.[GetPrototypeOf].

最后:

8.1.1.3 Function Environment Records , Table 17

[[HomeObject]] : If the associated function has super property accesses and is not an ArrowFunction, [[HomeObject]] is the object that the function is bound to as a method. The default value for [[HomeObject]] is undefined.

按照这个文档,好像getProtoPropViaSuper应该绑定(bind)到 y作为一种方法,但也许在 x 时以某种方式存储了绑定(bind)即使将函数分配给 y,也会创建并保留对象.但是,我无法从这些文档中解析发生的时间和地点。

如果有人能用通俗易懂的语言解释这种行为,我将不胜感激。 super如何确定它的值(value)?它看起来如何保持原来的状态 super语境?如果它持有原始对象,这似乎会导致内存泄漏,因为原始对象无法被垃圾回收。但也许 super引用是在准编译时确定的? (我说“准”是因为引用仍然可以被 Object.setPrototypeOf 改变)

最佳答案

perhaps that binding is somehow stored when the x object is created and retained even when the function is assigned to y.

是的,这正是发生的事情。 getProtoPropViaSuper 方法基本上关闭了定义它的对象。这存储在函数本身的内部 [[HomeObject]] 槽中,这就是它被保留的原因如果您将该方法分配给不同的对象,或者 - 更重要的是 - 在不同的对象上继承它1。对于对象字面量中的方法定义,它是字面量创建的对象;对于 classes 中的方法定义,它是类的 .prototype 对象。

1:为什么它需要是静态引用而不是像 Object.getPrototypeOf(this) 这样依赖于调用的东西,参见 here .

If it's holding onto the original object, it seems like that could cause memory leaks as the original object could not be garbage collected.

不,它不会导致比其他闭包更多的内存泄漏。当然,该方法阻止了它的 home 对象被垃圾收集,但是考虑到 home 对象是一个原型(prototype)对象——至少在正常使用中——它也在通常调用该方法的对象的原型(prototype)链中被引用,这不是问题。

I would really appreciate it if someone could explain this behavior in plain language. How does super determine its value?

它采用其绑定(bind)的 home 对象的原型(prototype),该对象是定义该方法的对象。但是请注意,访问 super 上的属性不会返回对属性的普通引用该对象,而是一个特殊的引用,当调用(方法)时,它将采用当前作用域的 this 值作为方法调用的 this 参数,而不是原型(prototype)对象.简而言之,

const x = {
method() {
super.something(a, b);
}
}

脱糖

const x = {
method() {
Object.getPrototypeOf(x).something.call(this, a, b);
}
}

class X {
method() {
super.something(a, b);
}
}

脱糖

class X {
method() {
Object.getPrototypeOf(X.prototype).something.call(this, a, b);
}
}

关于javascript - 与 'super' 相比,如何确定 'this' 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64395149/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com