欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

阮一峰ES6学习笔记

程序员文章站 2022-07-16 22:11:49
...

ES6的开发环境搭建

建立工程目录

先建立一个项目的工程目录,并在目录下边建立两个文件夹:scr和dist
* src:书写ES6代码的文件夹,写的js程序都放在这里
* dist:利用Bable编译成ES5代码的文件夹,在HTML页面需要引入这里的js文件

编写index.html:

文件夹建立好以后,新建一个index.html文件。

需要注意的是在引入js文件时,引入的是dist目录下的文件。

<script src="./dist/index.js"></script>

编写index.js

在scr目录下,新建index.js文件

let a = 1;
console.log(a);

初始化项目

打开终端或命令行公积进行初始化,默认全部同意

npm init -y

初始化完成后可根据自己的需求在package.json中修改初始化内容

全局安装Babel-cli

全局安装Bable的命令行

cnpm install -g babel-cli

本地安装babel-preset-es2015 和 babel-cli

cnpm install --save-dev babel-preset-es2015 babel-cli

安装完成后在package.json中会多出decDependencies选项

新建 .babelrc

在根目录下新建.babellrc文件,并打开录入以下代码

{
    "presets":[
        "es2015"
    ],
    "plugins":[]
}

建立完成后在终端输入

babel src/index.js -o dist/index.js

简化转化命令

在package.json中编写script字段

{
    "script":{
        "build":"babel src/index.js -o dist/index.js"
    }
}

修改好以后 直接可在命令行使用 npm run build 来进行转化


let和const命令

1.let命令

基本用法

ES6新增的let命令,用来声明变量,类似var,但是声明的变量,只在let声明的代码块中有效

{
    let a = 10;
    vat b = 9;
}

console.log(a);  //ReferenceError: a is not defined.
console.log(b);  //9

因为let的特性,在for循环中就更适合使用let命令

for (let a = 0; a < 10; a++) {
    //...
}
console.log(a);  //ReferenceError: a  is not defined.

上面的代码中a,只在for循环体内有效,在循环体外就报错。

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

上面的代码使用的var,最后输出的是10,变量i通过var声明,所以只有一个全局变量i.每次循环i都是改变值,而循环内被赋值给数组a的函数内部的console.log(i),里面的i指向的就是全局i,也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是10。

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

上面代码中,变量ilet声明的,声明的变量仅在块级作用域内有效,最后输出的是6。当前的i只在本轮循环中有效,所以每次循环的i其实都是一个新的变量,所以最后输出的是6。每一次循环的变量i的值之所以会递增,这是因为JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算的。

另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

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

上面代码正确运行,输出了3次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。


不存在变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象有点不是很合理。
为了纠正这种现象,let命令改变了语法行为,在声明之前只有就会报错。

// var 的情况
console.log(foo);  //输出undefined
var foo = 2;

// let 的情况
console.log(bar);  //报错
let bar = 2;

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”在这个区域,不搜外面的影响。

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

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

typeof x; // ReferenceError
let x;

typeof undeclared_variable // "undefined"


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

总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。