美文网首页
let和const

let和const

作者: bbh123 | 来源:发表于2019-03-14 10:20 被阅读0次

    块级

    for (let i = 0; i < 3; i++) {
      let i = 'abc';
      console.log(i);
    }
    // abc
    // abc
    // abc
    

    var 的情况变量提升

    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    

    暂时性死区

    var tmp = 123;
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    //“死区”比较隐蔽
    function bar(x = y, y = 2) {
      return [x, y];
    }
    bar(); // 报错,声明前使用
    function bar(x = 2, y = x) {
      return [x, y];
    }
    bar(); // [2, 2]
    // 不报
    //对比
    var x = x;
    // 报错
    let x = x;
    // ReferenceError: x is not defined
    

    不允许重复声明

    // 报错
    function func() {
      let a = 10;
      var a = 1;
    }
    // 报错
    function func() {
      let a = 10;
      let a = 1;
    }
    function func(arg) {
      let arg;
    }
    func() // 报错
    function func(arg) {
      {
        let arg;
      }
    }
    func() // 不报错
    

    global对象

    ES5 的顶层对象,本身也是一个问题,因为它在各种实现里面是不统一的。
    
    浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
    浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
    Node 里面,顶层对象是global,但其他环境都不支持。
    同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。
    
    全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
    函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
    不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
    // 方法一
    (typeof window !== 'undefined'
       ? window
       : (typeof process === 'object' &&
          typeof require === 'function' &&
          typeof global === 'object')
         ? global
         : this);
    
    // 方法二
    var getGlobal = function () {
      if (typeof self !== 'undefined') { return self; }
      if (typeof window !== 'undefined') { return window; }
      if (typeof global !== 'undefined') { return global; }
      throw new Error('unable to locate global object');
    };
    //所有环境拿到global
    // CommonJS 的写法
    require('system.global/shim')();
    // ES6 模块的写法
    import shim from 'system.global/shim'; shim();
    
    //顶层对象放入变量global
    // CommonJS 的写法
    var global = require('system.global')();
    // ES6 模块的写法
    import getGlobal from 'system.global';
    const global = getGlobal();
    

    获取函数名

    function breakfast() {}
    console.log(
      breakfast.name // breakfast
    )
    //匿名函数
    let breakfast = function () {}
    console.log(
      breakfast .name  // breakfast 
    )
    //非匿名函数
    let breakfast = function supreBreakfast() {}
    console.log(
      breakfast .name  // supreBreakfast,匿名函数的优先级低 
    )
    

    顶层对象属性

    //浏览器环境指的是window对象,在 Node 指的是global对象
    window.a = 1;
    a // 1
    a = 2;
    window.a // 2
    //6 种声明变量的方法var命令和function命令。let和const命令,import命令和class命令.
    var a = 1;
    // 在 Node 的 REPL 环境,可以写成 global.a
    // 采用通用方法,写成 this.a
    window.a // 1
    let b = 1;
    window.b // undefined
    
    //立即执行函数表达式 IIFE 写法
    (function () {
      var tmp = ...;
      ...
    }());
    // 块级作用域写法
    {
      let tmp = ...;
      ...
    }
    

    块级作用域和函数声明

    function f() { console.log('I am outside!'); }
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
      f();
    }());
    //实际运行的代码如下。
    // ES5 环境
    function f() { console.log('I am outside!'); }
    (function () {
      function f() { console.log('I am inside!'); }
      if (false) {
      }
      f();//I am inside
    }());
    
    // 浏览器的 ES6 环境
    function f() { console.log('I am outside!'); }
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
      f();
    }());
    // Uncaught TypeError: f is not a function
    //实际运行的代码。
    // 浏览器的 ES6 环境
    function f() { console.log('I am outside!'); }
    (function () {
      var f = undefined;
      if (false) {
        function f() { console.log('I am inside!'); }
      }
      f();
    }());
    // Uncaught TypeError: f is not a function
    
    //考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
    // 函数声明语句
    {
      let a = 'secret';
      function f() {
        return a;
      }
    }
    // 函数表达式
    {
      let a = 'secret';
      let f = function () {
        return a;
      };
    }
    
    const foo = {};
    
    // 为 foo 添加一个属性,可以成功
    foo.prop = 123;
    foo.prop // 123
    // 将 foo 指向另一个对象,就会报错
    foo = {}; // TypeError: "foo" is read-only
    const a = [];
    a.push('Hello'); // 可执行
    a.length = 0;    // 可执行
    a = ['Dave'];    // 报错
    
    //冻结对象
    const foo = Object.freeze({});
    // 常规模式时,下面一行不起作用;
    // 严格模式时,该行会报错
    foo.prop = 123;
    
    //彻底冻结对象及属性
    var constantize = (obj) => {
      Object.freeze(obj);
      Object.keys(obj).forEach( (key, i) => {
        if ( typeof obj[key] === 'object' ) {
          constantize( obj[key] );
        }
      });
    };
    

    相关文章

      网友评论

          本文标题:let和const

          本文链接:https://www.haomeiwen.com/subject/typfmqtx.html