es6之let、const命令

1 篇文章 0 订阅

1. let

  1. 声明的变量只在let块内有效
{
    var a = 2;
    let b =3;
}
console.log(a);//2
console.log(b);// b is not defined

适用于for循环计数器

for(let i = 0; i < 10; i++){
    
}
console.log(i);//i is not defined
var a = [];

for(let i = 0; i < 10; i++){
    a[i] = function(){
        console.log(i);
    };
}
a[6]();//6

for(var j = 0; j < 10; j++){
    a[j] = function(){
        console.log(j);
    };
}
a[6]();//10

上述命令中 let声明的i变量,仅在本轮循环中有效,每次循环的 i都是一个新变量,最终结果即为6

var声明的 j变量,是一个全局变量,所有数组a的成员里面的i均是指向同一个i,即为10

注:for循环设置循环变量的部分是一个父作用域,而循环体内部则是一个单独的子作用域

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

上述代码的运行结果即可说明。函数内部的变量i与循环变量i不在同一作用域,有各自单独的作用域

  1. 不存在变量提升
    console.log(a);//undefined
    var a = 100;
    
    console.log(b);//error
    let b = 50;
    

    var变量声明会出现变量提升,只是没有值

    let变量不存在变量提升,声明之前使用会抛出错误

  2. 暂时性死区

    本质: 只要进入当前作用域,所要使用的变量已存在,但是无法获取,只有等到变量声明的那一行代码出现,才可以获取和使用该变量

    var tmp = 123;
    
    if(true){
        tmp = 'abc';
        let tmp;
    }
    

    letconst声明变量前,对tmp赋值会报错,let声明变量 tmp之前,均属于tmp的死区

    两种隐蔽性死区
    function bar(x = y, y = 2){
        return [x,y];
    }
    bar();//error
    //参数x默认值等于另一个参数y时,此时y还没有声明,属于死区
    
    //修改
    function bar(x = 2, y = x){
        return [x,y];
    }
    bar();//[2,2]
    
    //unerror
    var x = x;
    
    //error
    let x = x
    
  3. 不允许重复声明

    let不允许在相同作用域内,重复声明同一个变量

    //error
    function func(){
        let a = 10;
        var a = 20;
    }
    
    //error
    function func(){
        let a = 10;
        let a = 20;
    }
    
    function func(arg){
        let arg;
    }
    func() //error
    
    function func(arg){
        {
            let arg;
        }
    }
    func() //unerror
    
  4. 块级作用域
    • 外层代码块不受内层代码块影响
    • 允许块级作用域任意嵌套
    • 内层作用域可定义外层作用域的同名变量

    浏览器的es6环境中,块级作用域内声明的函数,行为类似var声明的变量,其他环境中,类似let声明的变量

    注:

    • es6的块级作用域必须有大括号
    • 避免在块级作用域内声明函数,确实需要时,应写为函数表达式,而非函数声明语句
    • 严格模式,函数只能声明在当前作用域顶层

2. const 命令

声明只读的常量,一旦声明,常量值就不能改变

  • const一旦声明变量,立即初始化,不可留到以后赋值
  • const的作用域与let命令相同,只在声明所在的块级作用域有效
  • const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用
  • 不可重复声明
本质

const实际保证的是,变量指向的内存地址的值不可改变

  • 简单数据类型(number,string,boolean)

    值保存于变量指向的内存地址,等同于常量

  • 复合类型数据(object,array)

    变量指向的内存地址,保存的只是一个指向实际数据的指针,const仅能保证此指针固定,而它指向的数据结构是否固定,就不可控了

    //对象{}
    const foo = {}
    
    foo.prop = 123;
    foo.prop //123
    
    foo = {};//error
    

    常量foo存储的是一个地址,这个地址指向一个对象,这个地址不可变,但对象本身是可变的,不可把foo指向另一个地址

    const a = [];
    a.push('Hello'); // 可执行
    a.length = 0;    // 可执行
    a = ['Dave'];    // 报错
    

    常量a本身是一个可写的数组,但如果将另一个数组赋给a,则error

    冻结对象

    Object.freeze()方法

    //将对象及其属性彻底冻结的函数
    var constantize = (obj) => {
        Object.freeze(obj);
        Object.keys(obj).forEach((key,i) => {
            if(typeof obj[key] === 'object'){
                constantize(obj[key]);
            }
        })
    }
    

3.顶层对象属性

顶层对象,浏览器window;Node global

window对象的实体含义:指浏览器的窗口对象

  • 为保持兼容性,var命令和 function命令声明的全局变量,依旧是顶层对象的属性

  • letconstclass命令声明的全局变量,不属于顶层对象的属性

    var a = 1;
    window.a //1
    
    let b = 1;
    window.b //undefined
    

4. globalThis对象

JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。

  • 浏览器里面,顶层对象是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,内容安全策略),那么evalnew 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');
};

ES2020 在语言标准的层面,引入globalThis作为顶层对象。也就是说,任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this

垫片库global-this模拟了这个提案,可以在所有环境拿到globalThis

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值