书接上文留一下的思考对象中函数this问题,由此引出本篇的主角JavaScript的作用域链。
1、概念
- 每个函数在创建定义时,就已经规划好了自己专属的一条由内向外的查找变量的路线,称为作用域链。
- 一个函数把可用的所有作用域串联起来,就行成了当前函数的作用域链。
2、函数作用域链
- 当执行到某条语句时,Js引擎会自动延函数的作用域链查找要用的变量
<script>
var a = 10; // 全局作用域:变量 a
function fn1(){
var b = 20; // fn1作用域:变量 b
function fn2(){
var c = 30; // fn2作用域:变量 c
console.log(a);
}
fn2();
}
fn1();
</script>
<script>
var a = 10; // 全局作用域:变量 a
function fn1(){
var b = 20; // fn1作用域:变量 b
function fn2(){
var c = 30; // fn2作用域:变量 c
i = 100; // 作用域链上未声明的变量 i,
console.log(i);
}
fn2();
}
fn1();
</script>
小结: Js中只有两种局部变量
- 函数内var定义的
- 函数的形参变量
3、chrome调试
<script>
var name = 'The window';
var object = {
name: 'my Object',
getName: function(a) {
console.log(this.name, arguments);
return function() {
return this.name;
}
}
}
console.log(object.getName(1)());
// 等效于
// const returnFun = object.getName(1);
// const result = returnFun();
// console.log(result);
</script>
3.1 第一步:创建全局作用域对象(Global);
3.2 第二步:先调用object.getName(1),函数调用立即生成新的作用域,object调用的getName(),所以this指向object;
3.3 第三步:返回一个新的
fn();
3.4 第四步:执行
object.getName(1)()最后的()(即 第三步 返回的fn());
4、上章思考题
<script>
var lilei={
name: "冰墩墩",
intr: function(){
console.log(`我是奥运吉祥物${this.name}`)
}
}
</script>
intr: function(){}函数内形成自己的作用域,父作用域为window,如果去掉this,name在函数作用域内和父级作用域内都查找不到,所以不能去掉this。function()不能换成=>函数, 因为=>创建之初会始终指向外部对象,那么this将指向undefined。
this指向问题下章详谈,欢迎继续关注。