作用域
JavaScript 中的作用域分为 全局作用域 , 函数作用域 , 块作用域。
全局作用域
对于全局范畴内申明的变量,能够在任何中央拜访。
var messge = 'Hello'
function say(){console.log(message)
}
say(); // Hello
函数作用域
在函数内申明的变量,只能从该函数外部拜访。
function say() {
var messge = 'Hello';
console.log(messge);
}
say(); // Hello
console.log(greeting); // ReferenceError: messge is not defined
块作用域
ES6 引入了 let
和const
关键字,它们申明的变量只能从该代码块内拜访。
{
let messge = 'Hello';
console.log(messge);
}
console.log(messge); // ReferenceError: messge is not defined
动态作用域
在词法剖析时(编译时)确定。
let number = 42;
function printNumber() {console.log(number);
}
function log() {
let number = 54;
printNumber();}
log(); // 42
作用域链
JavaScript 运行时,引擎首先会在以后范畴内查找变量,如果找不到,会向父作用域查一层一层向上查找,始终找到顶层全局作用域,如果还是找不到就返回undefined
。
var g = 'Global hello'
function f1() {
var g1 = 'G1 hello';
function f2() {
var g2 = 'G2 hello'
function f3() {console.log(g, g1, g2)
}
f3()}
f2();}
f1(); // Global hello G1 hello G2 hello
运行剖析
执行上下文
执行上下文 是执行一段 JavaScript 的环境,它存储了执行代码的一些必要信息。执行上下文分 全局执行上下文 和函数执行上下文。
- 全局执行上下文 ,一个程序中只会有一个,函数之外的代码都在 全局执行上下文 中运行。
- 函数执行上下文 ,函数在每次调用时都会创立一个对应的 函数执行上下文。
执行上下文的蕴含 变量环境 (Variable environment
), 作用域链(Scope chain
),this
指向。
- 变量环境,函数外部所有的变量和对象援用和调用参数。
- 作用域链,以后函数之外的变量的援用组成。
this
指向。
从 JavaScript 运行时的内存构造来看,调用栈就是存储 执行上下文 的汇合。
案例
案例一
这是一个一般的 JavaScript 例子,运行流程剖析:
var msg = 'Global hello'
function say() {
var msg = 'Hello'
return msg;
}
var s = say();
console.log(message) // Hello
- 创立 全局执行上下文,而后入调用栈。
- 调用函数
say()
,创立say()
的函数执行上下文,并入调用栈。 - 执行完
say()
函数将后果返回,更新全局执行上下文里的s
变量。 - 将
say
函数的执行上下文弹出栈。
案例二
这个例子跟下面不同的是返回值是函数,这个匿名函数也称闭包,它拜访了函数内部的变量,即便内部 函数执行上下文 被弹出栈后,它仍然能够持有内部变量的援用。运行剖析如下:
var msg = 'Global hello'
function say() {
var msg = 'Hello'
return function() {console.log(msg)
};
}
var s = say();
s()
- 创立 全局执行上下文,而后入调用栈。
- 调用函数
say()
,创立say()
的函数执行上下文,并入调用栈。 - 执行完
say()
函数将后果返回,更新全局执行上下文里的s
变量,s
是函数类型,它仍然持有say
var = msg
援用。 - 将
say
函数的执行上下文弹出栈。 - 执行
s()
,创立s()
的函数执行上下文。 - 将
s()
函数的执行上下文弹出栈。
思考题
在脑海里动静执行上面代码。
题目一:
var msg = 'Global hello'
function getMsgFunc() {
var msg = 'Hello';
function getMsg() {return msg;}
return getMsg();}
console.log(getMsgFunc());
题目二:
var msg = 'Global hello'
function getMsgFunc() {
var msg = 'Hello';
function getMsg() {return msg;}
return getMsg;
}
console.log(getMsgFunc()());
题目三:
var msg = 'Global hello'
var obj = {
msg : 'Hello',
getMsgFunc : function(){return function(){return this.msg;};
}
};
console.log(obj.getMsgFunc()());
题目四:
var msg = 'Global hello'
var obj = {
msg : 'Hello',
getMsgFunc : function(){
var that = this
return function(){return that.msg;};
}
};
console.log(obj.getMsgFunc()());