我的头衔几乎总结了一切。
任何人都可以开导我...
“JavaScript中的'执行上下文'是什么?”
以及它与'this',吊装,原型链,范围和垃圾收集的关系如何?
答案 0 :(得分:49)
你问的是几个不太密切相关的不同概念。我将尝试简要介绍每一个。
执行上下文是语言规范中的一个概念 - 在外行人的术语中 - 大致相当于一个函数执行的'环境';也就是说,变量作用域(和作用域链,来自外部作用域的闭包中的变量),函数参数和this
对象的值。
调用堆栈是执行上下文的集合。
另请参阅this answer和this article。
范围的字面意思是:可以访问变量的范围。简单地:
var x;
function a() {
var y;
}
可以从任何地方访问 x
。调用a
时,x
将位于外部范围内。 (存储在范围链中。)
相比之下,y
只能由a()
中的代码访问,因为它仅限于a
的范围。这就是var
关键字的作用:将变量限制为本地范围。如果我们省略var
,y
将最终出现在全局范围中,通常被认为是一件坏事。
将提升想象成更多的编译时间。在JavaScript中,函数声明被“提升”到其范围的顶部。换句话说,它们在之前解析和评估任何其他代码。 (这与函数表达式相反,它们是内联计算的。)请考虑以下事项:
a();
b();
function a() { }
var b = function() { }
致a()
的呼吁将成功,因为其声明已被提升至最高位置;在程序执行开始之前,a
被自动分配。对b()
的调用将失败并显示TypeError
,因为直到第4行才会定义b
。
答案 1 :(得分:8)
你问了很多概念,但我们一个接一个地选择。了解他们。
运行代码的环境是Execution context
。
它是在执行代码时创建的。
Execution Context (Global)
包含3个重要的事项:
window
this
让我们看一个简单的例子来理解Global Execution Context
:
var a = "Hello World";
function b(){
}
当JS Engine运行上面的代码时,它会创建以下执行上下文(如图所示): Global Execution Context
现在让我们看看JS Engine如何创建Execution Context
(然后我们将挖掘并了解吊装):
考虑这种情况:
b();
console.log(a);
var a = "Hello World!";
function b(){
console.log("Called b!");
}
我可以调用函数b()
,即使它稍后被声明。
这意味着JS Engine在执行代码之前正在做一些事情,让我们看看:
JS Engine在执行任何代码时执行以下两个步骤:
创建阶段:
identifies variables & functions
(将在执行阶段使用)执行阶段非常简单易懂,
只要有函数调用,就会创建一个新的执行上下文
执行上下文堆栈: 调用函数时会发生什么:
function b(){
}
function a(){
b();
}
a();
现在首先要创建Global Execution Context
(如上所述)
然后执行开始,interpreeter遇到call to function
a()
和here a new execution context is created pushed on top EC
Stack
所以,只要你调用一个函数,就会创建一个新的EC&置于EC Stack之上。
所以现在EC for a()
是CREATED
interpreeter会执行代码
在a()
逐行
然后intrepreeter遇到call to function b()
,这就创造了
另一个EC
被推到顶部或EC
堆栈
当b()
完成后,它会从堆栈中弹出,然后a()
将完成&
一直到Global EC
答案 2 :(得分:3)
我已经解决了仅最密切相关的主题。
执行上下文是现有代码周围的包装器;其中包含您尚未编写的代码 ;但是由 JS Engine。
生成它包含以下内容 -
每次运行.js文件/应用程序时都会创建执行上下文。此创建阶段的第一步是提升。 JS Engine 为 代码中定义的所有变量和函数保留空间或设置内存。然后,当您的代码逐行执行时,将访问这些代码。
例如:
b();
console.log(a);
var a = "hi!";
function b() {
console.log("calling function");
}
此处,功能b()和变量a 在定义之前都会被访问,但是,由于提升,控制台将会不要抛出任何错误。
输出看起来像 - (尝试一下)
calling function
undefined
注意函数是如何完全执行的,但我们对变量有 undefined 。这是因为 Hoisting 对函数与变量的执行方式不同。整个函数被选取到内存中,但对于变量,空格保留为占位符,其值为 undefined 。然后,当引擎逐行执行您的代码时,将替换实际值。
我希望这能为你理清这个概念。
答案 3 :(得分:0)
"执行环境"是一个包含所有代码以帮助管理它的保护伞。它就像管理任何环境的经理一样。因为有很多词汇环境,因为在JavaScript应用程序中你有很多变量和函数,你需要一种方法来管理一切。什么是第一,什么是第二,等等,如果你没有"执行上下文"环境一切都变得很糟糕。因此,请考虑"执行上下文"包装器,管理代码的管理器。
答案 4 :(得分:0)
我想解决
1:执行上下文
JavaScript是一种单线程语言,这意味着一次只能执行一项任务。当JavaScript解释器最初执行代码时,它首先会进入全局执行上下文。从这一点开始每次调用一个函数都会导致创建一个新的执行上下文。
这就是混淆经常出现的地方,术语执行上下文实际上是针对所有意图和目的而更多地涉及范围而非上下文。这是一个不幸的命名约定,但它是ECMAScript规范定义的术语,所以我们有点坚持它。
每次创建新执行上下文时,它都会附加到执行堆栈的顶部。浏览器将始终执行执行堆栈顶部的当前执行上下文。完成后,它将从堆栈顶部删除,控制将返回到下面的执行上下文。
执行上下文可以分为创建阶段和执行阶段。在创建阶段,解释器将首先创建一个变量对象(也称为激活对象),该变量对象由执行上下文中定义的所有变量,函数声明和参数组成。从那里开始,范围链接下来被初始化,并且最后确定它的值。然后在执行阶段,解释并执行代码。
2:此上下文
什么是“这个”背景? 上下文通常由调用函数的方式决定。当一个函数作为一个对象的方法被调用时,它被设置为调用该方法的对象:
var obj = {
foo: function() {
return this;
}
};
obj.foo() === obj; // true
当使用new运算符调用函数来创建对象的实例时,同样的原则也适用。以这种方式调用时,函数范围内的this值将设置为新创建的实例:
function foo() {
alert(this);
}
foo() // window
new foo() // foo
当作为未绑定函数调用时,它将默认为浏览器中的全局上下文或窗口对象。但是,如果函数在严格模式下执行,则上下文将默认为undefined。
3:可变范围
变量可以在本地或全局范围中定义,它在运行时期间从不同的范围建立变量的可访问性。任何已定义的全局变量,表示在函数体外部声明的任何变量将在整个运行时间内存在,并且可以在任何范围内访问和更改。局部变量仅存在于定义它们的函数体内,并且对于该函数的每次调用都具有不同的范围。在那里,它仅在该调用中进行值赋值,检索和操作,并且不能在该范围之外访问。
ECMAScript 6(ES6 / ES2015)引入了支持块范围局部变量声明的 let和const 关键字。这意味着变量将被限制在其定义的块的范围内,例如if语句或for循环,并且不能在块的开始和结束花括号之外访问。这与var声明相反,var声明可以在定义它们的块之外访问。在let和const之间的区别是const声明,顾名思义,是常量 - 对值的只读引用。这并不意味着值是不可变的,只是变量标识符无法重新分配。
对于其他主题: GC:GC 原型设计:Prototyping
答案 5 :(得分:0)
执行函数时,将创建一个新的execution context
,其中包括一个称为variable environment
的本地内存和一个占位符的this
,它将在其执行上下文中引用任何内容是.
的左侧,正在调用该函数。
答案 6 :(得分:0)
我最近学习了全局执行上下文变量和函数。所以我的问题是函数是否有两个参数,函数参数是否有两个参数(值)。那么它在全局和调用堆栈中是如何工作的。这是代码
function myfunction(a,b){
return a*b;
}
var bana = myfunction(4,3);
console.log(bana);
答案 7 :(得分:-1)
JS中的EC(执行上下文)是什么?
简而言之,执行上下文是一个抽象的概念 评估和执行Javascript代码的环境。 只要有任何代码在JavaScript中运行,它就会在执行程序中运行 上下文。
有关更多深度的详细信息:https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0
答案 8 :(得分:-3)
我想一个简单的例子可以解释一切。
注意:function.call(object)
在function
object
// HTML
<p id="p"></p>
// JavaScript
function helloWorld() {
alert("HelloWorld: " + this);
}
var p = document.getElementById("p");
helloWorld(); // HelloWorld: [object DOMWindow]
helloWorld.call(window); // HelloWorld: [object DOMWindow]
helloWorld.call("String"); // HelloWorld: String // Note: "toString()"
helloWorld.call(p); // HelloWorld: [object HTMLParagraphElement]
helloWorld.call(new Date()); // HelloWorld: Tue Feb 21 2012 21:45:17 GMT+0100 (Central Europe Standard Time)
答案 9 :(得分:-3)
执行上下文是一个帮助管理正在运行的代码的包装器 在您的代码中,您将看到许多词汇环境意味着代码区域在{}之间但当前正在运行的区域是通过执行上下文来管理的。它可以包含您的代码,它还可以包含您在代码中编写的内容。