• 对JS作用域和作用域链的理解


    理解好javascript的变量作用域和链式调用机制对用好变量起着关键的作用,下面我来谈谈这两个概念的理解。
    (1)链式调用机制
    作用域链的定义:函数在调用参数时会从函数内部到函数外部逐个”搜索“参数,一直找到参数为止,如果没有声明就返回null,声明了没有赋值就返回undefined,就像沿着一条链子一样去搜索,这就是作用域的链式调用。
    javascrip的变量作用域跟python或者其他后端语言不同,变量一经声明,它的作用域就是全局的。在函数内部如果调用一个变量,就会发生上述的作用域链式调用的过程。
    例子:
    window.onload = function(){
         var foo = true;
         if(1==1){
            var bar = foo*2;
            console.log(bar);
            }
         console.log(foo);
    }
    打印的结果是:
    2
    true
    这段代码的实现过程大体是这样的:
    首先在if语句外部声明一个foo变量并给它定义赋值,在if语句内部找不到foo,就会到全局作用域去寻找foo变量。而if语句内部并没有改变foo的值,所以在外部打印foo时,它的值还是true。
     
    如果像下面一样稍微修改一下代码
    window.onload = function(){
          var foo = true;
          if(1==1){
               var foo = 2;
               bar = foo*2;
               console.log(foo);
              console.log(bar);
                }
          console.log(foo);
    }
    打印结果是:
    2
    4
    2
    if语句内部声明的变量foo把在if语句外面声明的变量foo覆盖了。
    所以在声明和引用变量的时候需要格外谨慎,一不小心,变量的值就改变了。
     
    在ES6之前,要防止变量被污染,要使用闭包这个概念。
    ES6为了解决这个问题,提出了两种声明变量的方法
    let关键字和const关键字
    1)let关键字
    可以将变量绑定到所在的作用域中,通常是{ ... }内部。
    例如:
    window.onload = function(){
           var foo = true;
           if (1==1){
               let foo = 2;
               var bar = foo*2;
               console.log(bar);
               }
           console.log(foo)
    }
    打印的结果是:
    4
    true
    显然,if语句内部声明的foo并没有影响到外部的foo,在if语句外部调用foo,还是原来的值true。
    2)const关键字
    const关键字同样是用来创建块作用域变量的,但其值时固定不变的。
     
    (2)js中的特殊情况:作用域链的改变
    以下语句或方法都会产生作用域链的改变
    1)with(实参){ } 语句
    2)try{ } catch(err){ } 语句
    2)eval()方法
    函数调用参数时都不会先执行函数内部的参数,而是调用此前已经定义过的参数,及函数被传递进来的实参。如果没用实参的相关属性值没有定义过,再调用函数内部的参数属性,即所谓的临时改变。(catch内部的err比较特殊,有优先调用的权力)
     
    (3)块作用域的理解
    块作用域的定义:函数内部的参数只能在函数/语句内部使用,函数/语句块外部不能使用,很多情况下块作用域是隐式的,即表面上看不出来。
    跟全局变量不同,块作用域内的变量不会链式调用。
    块作用域举例:
    1)for(var i)循环内部定义的参数i。在for循环结束后就会被销毁
    2)try{ } catch(err){ }语句内部的err对象。err只在catch内部调用,一旦函数执行完毕,马上销毁,即使函数外部想调用或者重新定义err也是无法调用到catch内部的err的
    3)with(var i)内部新定义的参数i
     
  • 相关阅读:
    如何保证 Redis 缓存与数据库双写一致性?
    如何合理地估算线程池大小?
    不用装工具,一条 Linux 命令就能实现文件上传下载!
    看了 Google 大神 Jeff Dean 的传说,我拜服了~
    div设置水平垂直居中
    "起用"与"启用"
    徇私舞弊
    精选排比金句20例
    一笔画图推
    一笔画
  • 原文地址:https://www.cnblogs.com/thomson-fred/p/9419355.html
Copyright © 2020-2023  润新知