zoukankan      html  css  js  c++  java
  • 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循环执行结束之后,也依然会存在于循环外部的执行环境中哟。

  • 相关阅读:
    从泛型类中继承
    DataGridView中的单元格提示错误信息
    C#中的转换
    C#的运算符重载
    解决android模块化升级方法
    个人总结如何在项目管理的实际软件开发工作的几个关键点和控制
    bash no such file or directory in ubuntu 1404
    java 遍历树节点 同时保留所有的从根到叶节点的路径
    ZendFramework2学习笔记 json和ajax
    POJ 2531-Network Saboteur(DFS)
  • 原文地址:https://www.cnblogs.com/wfblog/p/8934340.html
Copyright © 2011-2022 走看看