zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    用LazyLoad实现Javascript脚本与Css样式文件延迟加载
    SQL Server2008中删除重复记录
    数据访问层的单元测试
    Asp.net使用HttpModule压缩并删除空白Html请求
    Lazy<T>的应用之类内部字段与C#延迟加载
    Asp.net MVC3 RTM的源代调试
    Asp.net MVC 3 防止 CrossSite Request Forgery (CSRF)原理及扩展
    初识JVM
    JVM虚拟机栈简介
    Tomcat处理HTTP请求源码分析(上)
  • 原文地址:https://www.cnblogs.com/chenjunsheep/p/8678582.html
Copyright © 2011-2022 走看看