JS学习梳理(一)作用域和闭包

  1. 编译特点:实时编译、执行。性能保证:JIT、延迟编译、重编译
  2. 编译构成
    • 引擎
    • 编译器
    • 作用域
  3. 执行顺序:编译阶段 -> 执行阶段
    • 编译阶段:函数声明和变量声明都会被提升
    • 编译阶段:函数提升先于变量
    • 编译阶段:同名函数或变量会被覆盖
  4. 欺骗词法(非严格模式)
    • eval('str'),性能低
    • with,未找到匹配属性时,易自动创建成全局变量
  5. 函数作用域和块作用域
    • 立即执行函数
      (function foo() {})();
    • let(ES6),块作用域
      {
        console.log( bar ); // ReferenceError!
        let bar = 2;
      }
      function process(data) {
      // 在这里做点有趣的事情
      }
      // 在这个块中定义的内容可以销毁了!
      {
          let someReallyBigData = { .. };
          process( someReallyBigData );
      }
      var btn = document.getElementById( "my_button" );
      btn.addEventListener( "click", function click(evt){
      console.log("button clicked");
      }, /*capturingPhase=*/false );
    • const(ES6),块作用域,被修改后会报错
  6. 闭包
    //我们对这段代码行为的预期是分别输出数字1~5,每秒一次,每次一个。但实际上,这段代码在运行时会以每秒一次的频率输出五次6
    for
    (var i=1; i<=5; i++) { setTimeout( function timer() { console.log(i); }, i*1000 ); }

    //修改之后,通过立即执行函数来创建作用域。注意i,j之间的值传递。
    for (var i=1; i<=5; i++) {
    (function(j) {
    setTimeout( function timer() {
    console.log(j);
    }, j*1000 );
    })(i);
    }

    //for 循环头部的let 声明还会有一个特殊的行为。这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明。随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。
    for (let i=1; i<=5; i++) {
    setTimeout( function timer() {
    console.log( i );
    }, i*1000 );
    }
  7. 模块
    • 最常见的实现模块模式的方法通常被称为模块暴露
    • ES6 的模块没有“行内”格式,必须被定义在独立的文件中(一个文件一个模块)
  8. 动态作用域
    • JavaScript 并不具有动态作用域,它只有词法作用域,但是this 机制某种程度上很像动态作用域
    • 主要区别:词法作用域是在写代码或者说定义时确定的,而动态作用域是在运行时确定的。(this 也是!)词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。
  9. 其他
    • Google 维护着一个名为Traceur 的项目,用来将ES6 代码转换成兼容ES6 之前的环境。
    • “胖箭头”
      var obj = {
          count: 0,
          cool: function coolFn() {
              if (this.count < 1) {
                  setTimeout(() => { // 胖箭头语法
                      this.count++;
                      console.log("awesome?");
                  }, 100);
              }
          }
      };
      obj.cool(); // awesome?
    • bind
      var obj = {
          count: 0,
          cool: function coolFn() {
              if (this.count < 1) {
                  setTimeout(function timer() {
                      this.count++; // this 是安全的
                      // 因为bind(..)
                      console.log("more awesome");
                  }.bind(this), 100); // look, bind()!
              }
          }
      };
      obj.cool(); // more awesome

       

posted @ 2018-04-02 20:46  C.Jun  阅读(167)  评论(0编辑  收藏  举报