javascript的作用域以及闭包现象

1、 词法作用域

词法作用域就是定义在词法阶段的作用域,换句话说,也就是js的作用域时在定义阶段决定的,和调用无关。

1.1 作用域沿着作用链向上查找

<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
  //引擎执行console.log();在bar()内找不到a,向上查找,foo()也找不到,继续向上查找,在window全局中查找,找到a;
  function foo(){
      var b = a*2;
      function bar(c){
          console.log(a,b,c) // 2 4 8
      }
      bar(b*2);
  }
  var a =2;
  foo(2)

</script>
</html>

  

1.2 函数作用域,定义函数时,会创建自己的气泡(作用域),外部作用无法直接访问。

1.3 立即执行函数 IIFE(Immediately Invoked Function Expression)

IIFE函数一般在前加上;防止()和前面的函数结合。


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
  var a = 100;
  (function foo(){
      var a =1;
      console.log(a);
  })()
  console.log(a); //100
</script>
</html>

1.4块级作用域

javascipt没有块级作用域,块级定义的变量会污染上一级作用域


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
      for(vart i=1; i<10; i++){}
      console.log(i); //10
</script>
</html>

1.5 let语法

es6引入let语法可以解决js没有块级作用域问题,强行绑定所在作用域


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
      for(let i=1; i<10; i++){}
      console.log(i); //报错
</script>
</html>

let声明没有预解析,而且只能声明一次


let flag = 123;
let flag = 456; // 报错
console.log(flag);

console.log(num);  //报错
let num = 123;

1.6 变量提升

先有蛋后有鸡(先声明后赋值)

var a =1;分成var a 和a =2; 两步,第一步,定义声明是在编译阶段进行的,第二步赋值声明会被留在原地等待执行阶段。

<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
  console.log(a);
  var a =1;//undefined
  //第一步 var a ;第二步 console.log(a); 第三步 a =2;
</script>
</html>

函数优先

函数和变量的声明都会被提升,函数优先于变量


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
  foo(); //1
  var foo;
  function foo(){
      console.log(1);
  }
  foo = function(){
      console.log(2);
  }
</script>
</html>

1.7 动态作用域

js没有动态作用域,只有词法作用域


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
  function foo(){
      console.log(a) // 2
    // 如果有动态作用域,此处应该打印3

  }
  function bar(){
      var a =3;
      foo();
  }
  var a = 2;
  bar();

</script>
</html>

小练习


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
</body>
<script type="text/javascript">
  var b = 6;
  function test(){
      console.log(b); //undefined
      var b = 5;
      function a(){
          var b=1;
          console.log('a>>'+ b); //1
           
          function c(){
              console.log('c>>'+b);// 1
          }
          c();

      }    
      a();
  }
  test();
</script>
</html>

2、闭包

函数在当前词法作用域之外执行,即产生了闭包。


<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>

</body>
<script type="text/javascript">
  function foo(){
      var a = 2;
      function bar(){
          console.log(a)
      }
      return bar;
  }
  var baz = foo();
  baz(); //2
</script>
</html>
原文地址:https://www.cnblogs.com/Jason-lin/p/9264993.html