执行上下文
<script>
console.log("hello");
function demo(){
return 'my name is Tom';
};
demo();
</script>
执行上面这段代码可以在控制台看到输出 hello
问题1:这段代码是如何运行的呢?
答:javaScript代码其实都是在 可执行上下文 中运行的,下面3种类型的代码会创建一个新的执行上下文。
- 全局上下文:为运行代码主体而创建的执行上下文,以上面这段代码为例,全局上下文就是为运行 console.log("hello") 和 demo() 而创建的,也可以说它是为运行函数之外的js代码而创建的执行上下文。
<script>
function demo(){
var name = 'Tom';
console.log('demo age is:'+ age);
// VM1626:3 Uncaught ReferenceError: age is not defined
function say(){
var age=12;
console.log('my name is '+name)
// my name is Tom
console.log('my age is '+age)
// my age is 12
}
say();
};
demo();
</script>
-
函数上下文:还是被执行的时候会创建一个自己的执行上下文,可以看到执行上下文本质是一种作用域层级,里层的函数(say)拥有最大的作用域。
每个上下文创建的时候会被推入执行上下文栈。当退出的时候,它会从上下文栈中移除。
执行demo()时会为demo()函数创建一个上下文并将其推入执行上下文栈中。
执行say()时会为say()函数创建一个上下文并将其推入执行上下文栈中。当say函数执行完毕时会将其上下文从上下文栈中推出并销毁,然后执行下一个上下文也就是未执行完的demo函数。
var b=10;
eval(console.log(b))
// 10
- 使用 eval() 函数也会创建一个新的执行上下文。
作用域
<script>
function demo(){
var name = 'Tom';
console.log('demo age is:'+ age);
// VM1626:3 Uncaught ReferenceError: age is not defined
function say(){
var age=12;
console.log('my name is '+name)
// my name is Tom
console.log('my age is '+age)
// my age is 12
}
say();
};
demo();
</script>
作用域在编写完代码的时候就确定的
demo函数:
本地作用域:Tom say:ƒ say()
全局作用域:Global
this: Window
say函数:
本地作用域:Tom say:ƒ say()
闭包(Closure): name: "Tom"
全局作用域:Global
this: Window
虽然 执行上下文 和 作用域 都是在强调作用域,但是两者还是有区别的。
执行上下文:是在函数执行的时候创建的一个代码运行环境,执行上下文以堆栈的形式进行调用和销毁。
作用域:作用域在代码编写完成时确定的,强调的是变量和函数的访问权限
this
在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)