js中的执行环境及作用域

Posted 实践出真知

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js中的执行环境及作用域相关的知识,希望对你有一定的参考价值。

1、作用域链是在函数声明的时候确定的,而不是执行的时候确定的。

var x = 10;
function fn() {
    console.log(x);
}

function show(f) {
    var x = 20;
    
    f();
    
}

show(fn);  // 10

 2、JS中for循环变量作用域 : https://blog.csdn.net/kai_l/article/details/50913505

  for循环,不是函数,没有局部变量一说。内部  声明的变量  以及  括号里面的 i 变量  都是和 for在同级环境。

  es6 中的 let 声明的变量就有 块级作用域的区别了。

 

注意:es5 中的作用域只有 全局作用域局部作用域。(由函数 确定局部作用域,其他的都不能产生局部作用域;

     es6 中的作用域就有 全局作用域局部作用域块级作用域 (由{ }确定作用域,但只针对 let 声明的变量有效)。

(个人观点): 虽然一般用法中 var 变量可以实现的功能,let都可以实现(var有而let没有的效果有点反人类思维,一般不会那样用)。但是还是把 let 只是用于for循环变量的声明上。

3、回调函数的作用域 :声明这个回调函数的,执行函数外面 ,执行函数的 括号不会影响里面回调的作用域(亲测)

        var b = 0;
        function test(calback){
            var a = 8;
            calback()
        }

       test(function() {    // 回调函数的作用在 与调用函数test(),所在环境同级。
           console.log(a); // undefined
           console.log(b); // 0
       })

4、promise对象中then里面函数的作用域 :和回调函数一样,也是在声明这个函数所在函数内。调用函数的then不会影响then里面的作用域。(亲测)

       var dd = 9

        axios.get("./test.json").then(
            (res) => {
                var tt = 7;
                return Promise.resolve(res.data)
            },
            () => {
                alert(\'连接失败\')
            }
        ).then(
            (res) => {  // 这个函数前面的链式写法的有关函数都不会影响到,这个函数的作用域。即作用域和axios对象同级。
                console.log(dd); // 9
                console.log(tt); // undefined

            }
        )

 

 


 

 

首先来说说js中的执行环境,所谓执行环境(有时也称环境)它是javascript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据 ,决定了它们各自的行为。而每个执行环境都有一个与之相关的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

理解了执行环境,现在就看看什么是作用域链吧。每个函数都有自己的执行环境,当代码在执行环境中执行时,就会创建变量对象的作用域链。作用域链保证了对执行环境有权访问所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在的环境的变量对象,如果环境是一个函数,那么它的变量对象就是该函数的活动对象。作用域链的下一个变量对象来自包含(外部)环境,再下一个变量对象来自下一个包含环境。这样一直延续到全局执行环境,记住,全局执行环境的变量对象永远是作用域中的最后一个对象。

请看下面的例子:

var scope="global";
function foo(){
    console.log(scope);
}    
foo();

在这个例子中,函数foo()的作用域链包含了两个对象,一个是它自身对象,另一个是全局环境中的变量对象。因为我们可以在这个作用域链中找的scope,所以可以在函数内部里访问到它。

在看一个例子:

复制代码
var color = "blue";
function changeColor(){
    var anoterColor = "red";
    function swapColor(){
        var tempColor = anoterColor;
        anoterColor = color;
        color = tempColor;
        console.log(color);
    }
    swapColor();
}
changeColor();
复制代码

在这个例子中,有三个执行环境:全局环境、changeColor()的局部环境和swapColor()局部环境。我们来看看这个例子的作用域链是怎样的吧。

图中的矩形表示特定的执行环境。我们可以看到变量tempColor只能在swapColor()环境中访问到,而在changeColor()的局部环境还是全局环境中都无法访问到它。因此我们可以得到一个结论:内部的环境可以通过作用域链访问所有的外部环境,但外部的环境无法访问内部的环境中的任何变量和函数。每个环境都可以向上搜索作用域链,以查询变量和函数名;但是任何环境都不能通过向下搜索作用域而进入另一个执行环境。

作用域中我还想说说的是:js没有块级作用域

为什么说js没有块级作用域呢?我们来看下面的代码:

 

if(true){
  var color = "blue";  
}
alert(color);    //"blue"

 

咦,为什么color在if语句执行完毕后被销毁呢?哈哈,如果在C、C++或Java中,color确实会被销毁,但在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境中(在这里是全局环境)中。特别地,在for语句时要牢记这一差异,例如:

for(var i = 0;i< 10; i++){
doSomething(i);
}
alert(i);       //10

记住:在JavaScript中,由for语句创建的变量i即使在for循环执行结束之后,也依然会存在于循环外部的执行环境中哟。

 

以上是关于js中的执行环境及作用域的主要内容,如果未能解决你的问题,请参考以下文章

js之认识闭包

js基础梳理-如何理解作用域和作用域链?

浅谈JS执行环境及作用域

JS复习—执行环境及作用域

js中的作用域链

JavaScript 作用域 与 作用域链