美文网首页
关于ES6的let命令

关于ES6的let命令

作者: 听风_ead5 | 来源:发表于2018-10-18 19:35 被阅读0次
1、let的基本用法以及let和var的区别

(1) let与var一样是用来声明变量的,与var的区别是let所声明的变量,只在let所在的代码块内有效

eg1:
{
  let a = 10;
  var b = 1;
}
eg2:
for(let i=0;i<5;i++){
console.log(i);//输出1,2,3,4
}
console.log(i);//i is not defined

可以看上面这段代码,也就是说let声明的变量只能在{ }里面获取,在{}外面是获取不到,但是var声明的变量在{}内外都能获取到

(2) let未先声明变量就用变量会编译出错,但是var不会,会输出undefined
另外let不允许在同一作用域下声明已经存在的变量,即在同一作用域下不可以声明两个变量名相同的变量,会直接报错,但是var不会,可见let比var更加规范化

console.log(a);//报错:a is not defined
let a=1;

console.log(a);//undefined
var a=1;
}

(3) let在for循环内作用域问题1

{
for (let i = 0 /* 作用域a */; i < 3; console.log("in for expression", i), i++) {
    let i; //这里没有报错,就意味着这里跟作用域与上面a的作用域不同
    console.log("in for block", i);
}

(4) let在for循环内作用域问题2
1)关于下面eg1这段代码为什么输出结果是10呢?因为for里面的i的作用域是整个外部区域,所以,当调用a6的时候,其实运行的是console.log(i),而此时因为跑完循环,i的值是10,所以输出10

2)关于eg2输出结果是6,因为在ES标准中,有一段是关于CreatePerIterationEnvironment,也就是for语句每次循环所要建立环境的步骤,里面有提及有关词法环境的相关步骤(LexicalEnvironment),这与使用let时会有关。所以,如果你使用了let而不是var,let的变量除了作用域是在for区块中,而且会为每次循环执行建立新的词法环境(LexicalEnvironment),拷贝所有的变量名称与值到下个循环执行。

eg1使用var:
var a = [];
for (var i = 0; i < 10; i++) {
  // 作用域a
  a[i] = function () {
    // 作用域b
    console.log(i);
  };
}
a[6](); // 10


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

eg2:里面的代码其实就相当于下面这段代码

var a = [];
{ let k;
    for (k = 0; k < 10; k++) {
      let i = k; //注意这里,每次循环都会创建一个新的i变量
      a[i] = function () {
        console.log(i);
      };
    }
}
a[6](); // 6

(5) let的暂时性死区:只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响,
死区范围:在let命令声明变量tmp之前,都属于变量tmp的“死区”。
下面这段代码中,声明了一个全局对象tmp,并在if语句体对tmp进行重新赋值。正常来说,该语句是正确的,但是添加了“let tmp”后,运行该程序,就会报错,显示“ReferenceError”。大多数人往往会忽略到第一个声明的tmp变量作用域包裹了第二个tmp

例1:
var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

例2:
function bar(x = y, y = 2) {//y还没有定义的时候就使用y
  return [x, y];
}

bar(); // 报错

例3:
// 不报错
var x = x;
// 报错
let x = x;

(6)块级作用域
ES6以前变量的作用域是函数范围,有时在函数内局部需要一些临时变量,因为没有块级作用域,所以就会将局部代码封装到IIEF中,这样达到了想要的效果又不引入多余的临时变量。而块作用域引入后,IIEF当然就不必要了!

function f(){
   ...
   swap(var_a,var_b);
   (function swap(a,b){
       var tmp;
       tmp = a;
       a = b;
       b=tmp;
   })(var_a,var_b);
}

如上面的代码,tmp被封装在IIFE中,就不会污染上层函数;而有块级作用域,就不用封装成IIEF,直接放到一个块级中就好。

{
// 块级作用域写法
{
  let tmp = ...;
  ...
}
}

(7)ES6对函数的改革

{
function add(x,y){return x+y};//这是es5中定义函数的写法

var add=(x,y)=>x+y;//es6中我们可以这么搞:
add(1,2);//3,正常运行

var fun1=x=>x+1;
fun1(3);//4,当参数为1个的时候 可以再简单一点,当然复杂函数还是需要括号与大括号的

var fun2=(...args)=>{
  for(let arg of args){
      console.log(arg)
  }
};
fun2(1,2,3);//1,2,3配合rest参数,fun2()里面的实参1,2,3会传到args被当做args的值,...args是es6的扩展运算符,会把参数fun2()传递的实参作为一个数组
}

上面我们提到了扩展运算符,es6扩展运算符,也就是... ,作用是将一个数组转为用逗号分隔的参数序列。
那么问题就来了,我们为啥要用这么奇怪的东东涅,当然因为它能大大提高我们的开发效率。因此,我们可别小看这三个点。下面我们来总结两条这三个小点的用途:
(1)复制数组:
在es5时代,要想复制数组,最容易想到的是通过for循环一个一个push,或者来个slice()的,现在有了扩展运算符,直接一步就能搞定:

var  arr = [1,2,3,4,5];
var copy = [...arr];

(2)将类似数组的对象转换为真正的数组
任何类似数组的对象可以用扩展运算符转换为真正的数组。比如:

var newNode= document.querySelectorAll('div');
var array = [...newNode];
Array.isArray(array)   //true
var str = 'hello';
var aStr = [...str];
Array.isArray(aStr)    //true

(8)关于es6函数声明的行为方式:
1允许在块级作用域内声明函数。
2函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
3同时,函数声明还会提升到所在的块级作用域的头部。

上面的三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

根据这三条规则,在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。如下

// 函数声明语句
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 函数表达式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}

另外,还有一个需要注意的地方。ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

// 不报错
'use strict';
if (true) {
  function f() {}
}

// 报错
'use strict';
if (true)
  function f() {}

总结:

1、通过var定义的变量,作用域是整个封闭函数,是全域的 。通过let定义的变量,作用域是在块级或是子块中。

2、使用 let 声明的变量,在声明前无法使用,否则将会导致错误,并且不允许重复声明。

3、如果未在 let 语句中初始化您的变量,则将自动为其分配 JavaScript 值 undefined。

4、变量提升:不论var声明的变量处于当前作用域的第几行,都会提升到作用域的头部。
-var 声明的变量会被提升到作用域的顶部并初始化为undefined,而let声明的变量在作用域的顶部未被初始化

5、暂时性死区,在代码块内使用let命令声明变量之前,该变量都是不可用的,不受外部变量影响;

相关文章

  • ES6之 let 和 const 命令

    ES6 之 let 和 const 命令 1、let 命令 1.1、基本用法 ES6 新增了let命令,用来声明变...

  • ES6中的let和const命令

    ES6中的let和const命令 let命令 ES6 新增了let命令,用来声明变量。它的用法类似于var,但是...

  • ES6详解1

    es6语法 es6新增命令 let let 类似于 var 用来声明变量 ,let 命令所在的 代码块内才生效{l...

  • let 和 const 命令

    ES6 let 命令 ES6新增了 let 命令,用于声明变量,其用法类似于varlet 命令声明的变量仅仅在其所...

  • ES6 let 和 const 命令

    目录 1、let命令 2、块级作用域 3、const命令 1、let命令 ES6 新增了let命令,用来声明变量。...

  • es6个人总结

    let命令es6新增let命令,类似于var命令,但是声明的变量只是在let命令所在的代码块有效,并且let不可以...

  • let 和 const 命令

    let 命令 块级作用域 const 命令 顶层对象的属性 global 对象 let 命令 基本用法 ES6 新...

  • let 和 const 命令

    let 命令 块级作用域 const 命令 顶层对象的属性 global 对象 let 命令 基本用法 ES6 新...

  • ES6 学习笔记-let

    let 和 const 命令 1. let命令 基本用法 ES6 新增了let命令,用来声明变量。它的用法类似于v...

  • let和const命令

    ES6学习 let和const命令 1. let命令 基本用法let命令,用来声明变量。他的用法类似于var,只在...

网友评论

      本文标题:关于ES6的let命令

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