第二章 let 和const命令

作者: 三多_250e | 来源:发表于2019-11-06 20:53 被阅读0次
  1. let命令
  2. 块级作用域
  3. const命令
  4. 顶层对象的属性
  5. globalThis 对象

可抽取出的面试题

  1. es6中一共有多少声明变量的方法?例如:var和function
  2. 下面各输出什么?
var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10


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

3.关于块级作用域,for循环有何特殊之处?(提示:父作用域,子作用域)
4.说一下变量提升和暂时性死区?
从var举例说变量提升,暂时性死区用let举例
5.es6中关于顶层对象属性和全局变量的差异?(var和let举例 )

1. let命令

es6新增let命令,用来声明变量,用法类似于var,但是用let所声明的变量,只在let所在的代码块中有效,代码块外引用,为undefined,
使用场景,for循环中计数器特别适合
区别例子:

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

由于上面代码中,i是全局变量,在全局范围内有效,所以全局只有一个变量i,每一次循环,变量i的值都会发生改变,而循环内被赋值给a数组的函数内部的console.log(i)指向的是就是全局的i,所以是最后一轮输出的i的值,也就是10,
如果使用let声明,变量仅在代码块内有效,所以最后输出的是6。
另外,for循环有一个特别的作用域,就是设置循环变量的那一部分是一个父作用域,而循环内部是子作用域,

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

上面代码运行了三次abc,这就说明for循环中,函数体重的变量i和循环变量i不在同一个作用域,有各自单独的作用域。

不存在变量提升

var变量会发生‘变量提升’现象,即变量可以在声明之前使用,值为undefined,这种现象多少有点奇怪,按照一般的逻辑,变量应该在声明后才能使用。
为了纠正这种现象,let命令改变了语法行为,它所声明的变量,一定要在声明后使用,否则报错,

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域了,不再受外部影响。

tem  = 123;
if(true){
  tem = 'abc';  //ReferenceError
  let tem;
}

上述代码,存在全局变量tem,但是块级作用域内let又声明了一个tem这个时候,其实是后者这个let声明的tem绑定到了这个if执行体中的跨级作用域,所以这时候报错就变成前面提到的不存在变量提升了,因为此时的tem是绑定的let声明的这个,es6明确规定:如果代码块中存在let和 const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域,凡是在声明前就使用这些变量,就会报错。这在语法上,称为“暂时性死区”

不允许重复声明

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

块级作用域

为什么需要块级作用域?

es5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种情景,内层变量可能会覆盖外层变量。

var tmp = new Date();
function f(){
  console.log(tmp);
  if(false){
    var tmp = 'hello word';  
  }
}
f()//undefined

上面代码的原意是if代码块外的tmp使用外层声明的,if代码块内的使用内层声明的变量。但是,函数f执行后,输出结果是undefined,原因在于变量提升,导致console使用 的是if代码块内的,但是if代码块并没有执行,所以tmp是undefined。
第二种是for循环后,计数变量没有及时回收,一直存在于全局变量中,

块级作用域与函数声明

函数能不能在块级作用域之中声明?这是一个相当令人混淆的问题。
es5规定,函数只能在顶层作用域和函数作用域中声明,不能在块级作用域中声明。但是浏览器没有遵守这个规定,为了兼容以前的代码,还是支持在块级作用域中声明函数,ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
另外,还有一个需要注意的地方。ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

3const命令

const是一个只读常量,一旦声明,常量的值不可改变。这意味着const一旦声明,就必须立刻初始化,不能留到以后赋值,
const的作用域与let相同,只在声明所在的块级作用域内有效。
const命令声明的常量也是不提升,存在暂时性死区,只能在声明后使用,在相同作用域内,也不可重复声明

es6声明变量的六种方法

es5只有两种声明变量的方法,var和function,但是在es6中,除了添加了上面我们提到的let和const外,后面章节还会提到,两外两种声明变量的方法:import命令和class命令。所以es6一共有6种声明变量的方法。

4.顶层对象的属性

顶层对象,在浏览器中指的是window对象,在Node中指的是global对象,es5之中,顶层对象的属性和全局变量是等价的。

window.a = 1;
a // 输出1
a = 2;
window.a //2

上面代码中,顶层对象的属性与全局变量的赋值,是同一件事。
顶层对象的属性与全局变量挂钩,被认为是JavaScript语言最大的设计败笔之一。这样的设计带来了几个很大的问题。
首先是没法在编译时就报出变量未声明的错误,只有在运行时才知道;
其次,程序员很容易不知不觉的就创建了全局变量,最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程。另一方面,window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。
es6为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令,const命令,class命令声明的全局变量,不属于顶层对象的属性。也就是说,从es6开始,全局变量将逐步的与顶层对象属性脱钩。

5. 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,内容安全策略),那么eval、new Function这些方法都可能无法使用。

综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。

相关文章

  • let和const

    新的赋值语句let和const let和const命令

  • ES6的let 和 const 命令

    let 和 const 命令 let 命令 块级作用域 const 命令 顶层对象的属性 gl...

  • 2019-03-03

    es6 第二章 let和const命令 let 基本用法 let和var的区别let:只在定义的代码块中起作用va...

  • ES6需要记忆理解的地方

    let和const命令 1、let和const均无变量提升。2、let变量指向的地址可变,const指向的地址不可...

  • 重读 ES6(一)

    一、let 和 const 命令 let 命令 let 与 var 的区别:let 声明的变量只在 let 命令所...

  • js 中var contst let 之间的区别

    ECMAScript 6 新增 const 和 let 命令,用来声明变量。 那么const,let和var 在声...

  • es6常用语法(一)

    let 和 const 命令 let 命令 只在let命令所在的代码有效 let命令,用来声明变量。它的用法类似于...

  • es6总结一

    es6基础 let和const命令 let和const用于声明变量let跟var的区别 1、let定义过的变量不能...

  • ES6笔记

    let 和 const ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一...

  • ECMAScript 6 入门

    1.let 和 const 命令 let 命令 基本用法 ES 6 新增了 let 命令,用来声明变量,它的用法类...

网友评论

    本文标题:第二章 let 和const命令

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