JS 函数作用域

前些日子,我专门去看了箭头函数,但是阮一峰作者中的箭头函数文章里有写到这样一句话:

在定义对象方法的时候不适合使用箭头函数,因为对象不构成单独的作用域”,作者的原代码如下:

const cat = {
    lives:9,
    jumps:() => {
        this.lives--;
    }
}
// 原作者解释:cat.jumps()方法是一个箭头函数,这是错误的。调用cat.jumps(),如果是普通函数,该方法内部的this指向cat;如果携程上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义的时候作用域是全局作用域。

作者的那句话让我突然很困惑,因为我一直以为ES6中只要是{}就是一个块级作用域,但确实就是这样理解的。作者想表达的是:对象是因为箭头函数才不构成独单的作用域。

那么接下来将探讨以下几个问题:

一、执行上下文和作用域的关系是什么?

上下文中的代码在执行的时候,会创建变量对象的一个作用域链。作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域链的最前端。

1.1 执行上下文

1.1.1 什么是执行上下文

每个上下文都有一个关联的变量对象,而这个上下文中定义的所有变量和函数都存在于这个对象上。
在浏览器里,全局上下文是window对象,var所声明的变量和函数都会称为window对象的属性以及方法。但let和const的顶级声明不会定义在全局上下文中,但在作用域链解析上效果是一样的。全局上下文的变量对象始终时作用域链的最后一个变量对象。

1.1.2 执行上下文的作用、生成、销毁

变量或者函数上下文的作用:决定他们可以访问哪些数据,以及它们的行为。
销毁:在其所有代码都执行完毕后,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。ECMAScript程序的执行流就是通过这个上下文栈进行控制的。

1.1.3 上下文的分类(用例子解释)

var color = "blue"; 
function changeColor() { 
 let anotherColor = "red"; 
 function swapColors() { 
 let tempColor = anotherColor; 
 anotherColor = color; 
 color = tempColor; 
 // 这里可以访问 全局的color、anotherColor 和 tempColor 
 } 
 // 这里可以访问 全局的color 和 anotherColor,但访问不到 tempColor 
 swapColors(); 
} 
// 这里只能访问 color 
changeColor();

上面有三个上下文:全局上下文、changeColor()的局部上下文、swapColors()的局部上下文。
从上面不同上下文中可以看出:局部上下文首先会从自己的变量对象搜索变量和函数,搜不到会去搜索上一级的变量对象。【函数参数被认为是当前上下文的变量,因此也跟着上下文中的其他变量遵循相同的访问规则】

2.1 作用域

2.1.1 作用域是什么时候形成的?

function a() {
    function b() {
        var b = 1;
    }
    var a = 123;
    b();
}
var c = 2;
a();

在a函数被定义时,生成以下作用域:

 执行a函数,生成如下作用域:

能看到有个Activation Object对象(活动对象),这表示上下文是函数时,活动对象用作变量对象。活动对象最初只有一个定义变量:arguments【全局上下文没有这个变量】。

a函数执行时,b函数定义,b定义时,生成如下作用域,从图中可以看出,b在定义时的作用域直接指向a执行时生成的执行期上下文,它们共用相同的执行期上下文。

 2.1.2 作用域链增强

上下文主要有全局上下文、函数上下文、eval()内部调用,但会有其他方式来增强作用域链。某些语句会导致在作用域链前端临时添加一个上下文,这个上下文在代码执行后会被删除。遇到下面任意一种情况都会出现这种现象:

1.try/catch语句的catch:创建一个新的变量对象,这个变量对象会包含要抛出的错误对象的声明。

2.wtih语句:会向作用域链前端添指定的对象;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值