从逻辑的角度来看,JavaScript执行上下文和JavaScript对象是一样的吗?

时间:2018-01-24 08:37:04

标签: javascript

我对JavaScript的理解是,在脚本执行时会创建一个全局执行上下文 - 我理解为保留内存空间中的一系列键值:值对 - 非常类似于常规JavaScript对象。

在功能执行时,创建一个新的执行上下文,可以访问父母'执行上下文。这似乎(对我而言)至少相当于重新初始化JavaScript执行环境。除了最初在全局对象中设置的key:value对之外,需要将其添加到新的执行上下文,因为子执行上下文可以访问父键的值:值对。

例如:

function Y() {
   this.prop = 4;
};

Y.prototype.doY = function() {
  console.log(this.prop);
};

function X(){
  this.prop = 5;
  this.y = Object.create(Y.prototype);
  Y.call(this.y);
};

// I can instantiate the object like so:
var x = new X();

// Which is equivalent to the following:
var x = Object.create(X.prototype);
X.call(x);

// Then I can add a function to the object that the X constructor points to via the X.prototype reference:
X.prototype.doX = function() {
  console.log(this.prop)
};

// And then i can execute doX() in the context of the x object
x.doX(); // 5
x.y.doY(); // 4

执行时,doX函数创建从x对象中引用的执行上下文。反过来,x对象在全局对象中被引用。

同样,在执行时,doY函数会创建一个从x.y对象中引用的执行上下文。

在我看来,从逻辑的角度来看,由函数执行创建的执行上下文基本上等同于JavaScript对象:

  • 两者都允许变量声明对父对象/执行上下文不可见
  • 两者都包含对父对象/执行上下文的某种内部引用

似乎对象和执行上下文都只是一个key:值列表,整个列表由一个(只有一个)父对象引用(即y对象作为引用存在于x执行上下文) - 或全局对象作为根父对象(x对象作为全局执行上下文中的引用存在)。

所以问题是:JavaScript执行上下文是否与JavaScript对象相同?如果没有,有什么区别?

这个问题:Are Execution Context and Variable Object actually same thing in JavaScript?提到在实现方面,执行上下文和对象不是一回事。

说执行上下文是否继承自Object是否正确?或者对象/执行上下文的实现是完全不相关的...我可以看到的一个区别是,在创建时,执行上下文被处理'从上到下(词汇上讲)允许作者指定命令性命令 - 即指示计算机做事。但就建筑而言,这种差异似乎是对象概念的延伸,而不是完全不同的东西。

在我看来,正在运行的JavaScript环境'如果存在这样的东西,基本上就是一棵树。根节点是全局执行上下文,创建对象将节点添加到根节点,或者(如上面的y的情况)将节点添加到子节点。子节点然后通过属性引用父节点,以允许对父执行上下文进行作用域。

然后就闭包而言,涉及执行上下文的创建(和执行),返回时,结果对象看起来像一个常规对象,因为执行上下文'由闭包引用将永远不会再次执行(即,相同的函数,重新执行将创建一个新的执行上下文和闭包)。

所以来自"应用"从某种程度上说,this - >即对当前执行上下文的自引用,与进行函数调用的对象不同(除了使用callapplybind时?即在x.y.doY()的情况下,从doY对象调用函数x.y

3 个答案:

答案 0 :(得分:4)

Execution contexts概念对象,是的,规范中的其他几项内容也是如此。这并不能使它们与JavaScript对象“相同”。它们是规范设备,可能根本不存在于运行时;代码不能直接引用它们。要获得完整图片,请阅读规范中的Executable Code and Execution Contexts

  

JavaScript执行上下文是否与JavaScript对象相同?

没有。 JavaScript对象可以直接由代码引用,具有原型,并且具有针对它描述的特定行为,这些行为没有针对执行上下文等描述。

  

说执行上下文是否继承自Object?

是否正确?

不,规范中没有任何内容表明情况属实。

  

在我看来,如果存在这样的“运行JavaScript环境”,基本上就是一棵树了。

相当间接地排序。规范没有描述从执行上下文到其父或子上下文的任何链接。相反,属于上下文状态(特别是LexicalEnvironment和VariableEnvironment状态组件)的lexical environment对象具有指向其父级词汇环境的链接,以便进行绑定解析。 (父lexenv在规范中没有指向其子节点的链接。)但它们也纯粹是一种规范设备,它可能在运行时不存在,也不能直接被代码引用。

因此将它们视为对象是完全正确的,这就是规范如何描述它们,但它们不是通常理解术语的JavaScript对象 - 代码可以直接引用和操作。

答案 1 :(得分:2)

不,他们不是一回事。完全没有。

首先,您似乎将执行上下文与环境记录混淆。前者基本上是调用堆栈帧,后者存储变量值并形成如您所述的树。让我们谈谈环境记录。

环境记录具有键值映射和指向其父环境的链接。在这方面,它们类似于具有其属性和原型链接的JS对象。实际上,在with语句或全局范围内,所谓的对象环境记录由实际的JS对象支持。
但是,它们仍然非常不同。大多数环境记录是声明性的,这意味着它们的形状在使用之前就已确定。它们就像一个不可扩展的对象。他们也不能拥有getter / setter属性。他们在更多细节方面有所不同。

但最重要的是,环境记录只是specification type values。它们" 是规范工件,不一定与ECMAScript实现中的任何特定实体相对应。规范类型值可用于描述ECMAScript表达式评估的中间结果,但这些值不能存储为对象的属性或ECMAScript语言变量的值。"所以不,他们根本不会继承Object

答案 2 :(得分:1)

您的问题似乎在于:执行上下文记录的内容无法记录在javascript对象中?

你已经有了很好的答案。所以我的贡献将是实际的例子。

您如何从键/值角度管理以下2个示例:

// Execution context of anonymous functions
(function (x) {
    var y = x+1;
    console.log(y);
}) (1);

// Life cycle of objects versus reference
var x = {a:1};
var y = x;
x = {b:1};
console.log(y);

如果您开始发明不在代码中的密钥,您应该意识到这种方法是有限的。所以,如果你超越极限就不行。