今天看到一个华为员工的爆料,突然被领导电话召唤,说有机会去非洲上班,薪资是45000元一个月,五年合同,双倍年终奖。
员工一听,瞬间心动了,但也有些犹豫。毕竟,出国工作不仅仅是薪水上的吸引,还涉及到生活环境、工作内容以及是否真的能够适应新的工作和生活方式。
但我的建议是,这种工作机会确实需要谨慎考虑。薪资诱人,但不同地区的生活成本和工作环境差异极大。
你要考虑的不仅仅是薪水,还有工作是否符合自己的发展方向、工作内容是否有挑战、是否能在新的地方保持生活质量。如果能先去考察一下,了解清楚相关情况,再做决定会更稳妥。
今日面试题
好了,瓜吃完了,我们回归正题,今天我们来聊聊一个面试中经常被问到的概念:JavaScript中的执行上下文和执行栈。听到这些词可能大家有点懵逼,尤其是刚接触JavaScript的同学。但是,不用担心,今天我会用最简单、最直白的方式把这个问题给搞懂。
首先,执行上下文听起来可能有点抽象,其实它就是JavaScript代码执行的一个环境,简单来说,任何一段JavaScript代码的执行都一定会在某个执行上下文中进行。
每当你调用一个函数时,JavaScript引擎就会为这个函数创建一个新的执行上下文;同样,整个程序从头到尾都在全局上下文中执行。
那么,执行上下文有几种类型呢?其实分为三种:
全局执行上下文(Global Execution Context):这个是唯一的。换句话说,浏览器中只有一个全局上下文。全局对象就是
window
(在浏览器中),this
指向的也是这个全局对象。函数执行上下文(Function Execution Context):这个是动态的,每当你调用一个函数时,都会创建一个新的执行上下文。也就是说,每个函数都有它独立的执行上下文,彼此之间互不干扰。
eval执行上下文(Eval Execution Context):说实话,这个用得不多,而且大多数情况下不推荐使用。它是执行
eval()
函数里的代码时的执行上下文。
我们可以来看一个简单的代码示例,帮助大家理解全局上下文和函数上下文的区别:
let a = 'Hello World!';
function first() {
console.log('Inside first function');
second();
console.log('Again inside first function');
}
function second() {
console.log('Inside second function');
}
first();
console.log('Inside Global...');
执行时,首先进入的是全局执行上下文。 a
这个变量、first
和second
函数都会被存储在全局的上下文中。当 first()
函数被调用时,它会创建一个新的执行上下文,将自己压入执行栈(我们稍后会讲到执行栈)。在 first()
函数内部调用second()
时,second()
会创建自己的执行上下文,同样压入栈中。
所以,总结一下,执行上下文就是你代码执行时的环境,它决定了变量、函数等的生命周期和作用域。
执行上下文一旦被创建,它就会经历三个阶段:
创建阶段:这个阶段发生在函数被调用时,但在代码实际执行之前。创建阶段做了三件事情:
确定 this
的值:this
的值是在执行时才确定的,不能在定义时就知道。词法环境(Lexical Environment)组件创建:词法环境决定了作用域的绑定。 变量环境(Variable Environment)组件创建:这里会存储所有的 var
变量。
执行阶段:在这个阶段,代码开始执行。如果有变量和函数声明,它们会被赋予初始值。
回收阶段:当执行上下文的任务完成后,它会从执行栈中弹出,等待垃圾回收机制清理。
说完了执行上下文,再来说说执行栈。执行栈也被称作“调用栈”,它是一个后进先出(LIFO)的结构。简单来说,执行栈就像一座塔,每次执行一个函数,它就会被压入栈顶;当函数执行完成后,它就会被弹出栈。
让我们看一段代码来更清楚地了解:
let a = 'Hello World!';
function first() {
console.log('Inside first function');
second();
console.log('Again inside first function');
}
function second() {
console.log('Inside second function');
}
first();
console.log('Inside Global...');
执行代码时,首先会创建一个全局执行上下文,并将其压入执行栈。 当 first()
函数被调用时,新的执行上下文会被创建并压入栈中。first()
内部调用second()
时,second()
的执行上下文会再次被压入栈中。当 second()
执行完毕,它的上下文会从栈中弹出,接着执行first()
中的剩余代码。最后,当 first()
执行完毕,它的上下文会被弹出,最后执行全局上下文中的代码。
执行栈的顺序总是后进先出,因此你会看到最后一个调用的函数会先执行,执行完毕后再返回到前一个函数的执行。
我们为什么要了解执行上下文和执行栈?理解执行上下文和执行栈不仅能帮助你理解JavaScript代码的执行顺序和作用域,还能让你更好地理解一些重要概念,比如闭包、作用域链、this
的指向等。
举个例子,变量提升就是通过理解执行上下文的创建过程来解释的。当代码进入到创建阶段时,var
声明的变量会被提升到函数或者全局作用域的顶部,但它们的赋值会等到执行阶段才进行。你可以通过下面的代码来验证:
console.log(a); // undefined
var a = 10;
console.log(a); // 10
在创建阶段,a
会被提升到作用域的顶部,但它的赋值操作还没有执行,因此第一次打印a
时输出undefined
。
目前,对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
虎哥私藏精品 热门推荐 虎哥作为一名老码农,整理了全网最全《前端资料合集》。