0


ECMAScript--》 ES6语法规范 ## Day1

1. 简介

ECMAScript6.0也称ES6,是JavaScript 语言的下一代标准,2015 年 6 月正式发布,目的是使JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

1.1 ES6与JavaScript的关系

ES6发布的第一个版本就成为规定了浏览器脚本语言的标准,并将这种语言称为ECMAScript,这种标准一开始就针对JavaScript语言制定,取名的原因与公司和商标有关,总之ES6和JavaScript的关系是,前者是后者的规范,后者是前者的一种实现。

1.2 Node下查看默认没有打开的ES6实验性语法

// Linux & Mac
$ node --v8-options | grep harmony

// Windows
$ node --v8-options | findstr harmony

这里就拿Windows下举例

1.3 ES6代码转ES5代码

利用Babel转换器实现代码转换,原始代码用了箭头函数,Babel将其转换普通函数。

// 转码前
input.map(item => item + 1);

// 转码后
input.map(function (item) {
  return item + 1;
});

2. let和const的变量声明及特点

2.1 let的命令用法

let是ES6新增的命令,用来声明变量,方法类似于var,但所声明变量只在其规定的let命令所在代码块内有效,例如

{
    var a = 1;
    let b = 2;
}
console.log(a);
console.log(b);

上面代码分别用var 和 let 声明两个变量并在外调用,结果let声明变量报错,表明let只能在规定代码块内才能使用。

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

上面代码是用let声明,声明的变量仅在块级作用域内有效,所以说当前的i只在本轮循环有效,因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量

i

时,就在上一轮循环的基础上进行计算,所以每次循环的i都是一个新的变量,所以最后输出的就是对应的值。

2.2 let的变量提升情况

我们知道,如果我们使用var命令,在预解析的作用域下,会导致变量提升,详情请看我相关博客的介绍:JavaScript入门到精通(四)连载_亦世凡华、的博客-CSDN博客

ES6为了纠正这种现象,使得let命令改变了语法行为,它所声明的变量一定要在声明后,否则会报错。例如:

// var
console.log(a); // 输出undefined
var a = 1;
// let
console.log(b); // 报错ReferenceError
let b = 1;

var的声明下,由于变量提升会先声明a但不赋值,执行输出语句当然是undefined,而let声明下,由于没有变量提升,输出b前,b是不存在的,只能抛出一个错误

2.3 let的重复声明情况

let不允许在相同作用域内重复声明同一个变量;所以也不能在函数内部重新声明参数。否则报错

function fn() {
  let a = 1;
  let a = 2;
} // 报错

function fn() {
  let a = 1;
  var a = 2;
} // 报错

function fn(a) {
  let a;
}
fn() // 报错

function fn(a) {
  {
    let a;
  }
}
fn() // 不报错

2.4 let的暂时性死区

在代码块内,使用let命令声明变量之前,该变量都是不可使用的,凡是在声明之前就使用这些变量,就会报错,这在语法上,称为“暂时性死区(TDZ)”。

if (true) {
  // TDZ开始
  a = '张小凡'; // ReferenceError
  console.log(a); // ReferenceError

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

  a = '张小凡';
  consle.log(a); // 张小凡
}

上面代码中,在

let

命令声明变量

a

之前,都属于变量

a

的“死区”,ES6规定暂时性死区主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的错误,这种规定显然很容易避免了这样的错误。

2.5 const的命令用法

const声明的是一个只读变量,一旦声明,变量的值无法更改,否则报错

const a = '张小凡';
console.log(a);

a = '666';
console.log(a);

const声明的变量不能改变值意味着,一旦const声明就必须进行初始化,不立即赋值会立马报错。

const a;

2.6 const的其它特点

const和let一样,只在声明所在的块级作用域内有效,声明的常量也不存在变量提升,同样存在暂时性死区,声明的常量也与let一样不可重复声明。

2.7 const的实际作用

const保证的并不是变量的值不能变动,而是变量指向的那个内存地址所保存的数据不能变动。

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

上面代码中,常量

a

是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给

a

,就会报错。

3. ES6的6种声明变量方式

常见的:var 和 function;ES6添加的 let 和 const ;以及另外两种 import 和 class 命令

4. 变量的赋值-解构

ES6允许从数组和对象中提取值,对变量进行赋值,被称为“解构”

4.1 数组的解构

以数组方式进行变量赋值属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予相对应的值,这样的赋值方式比以前的赋值方式更简单和清楚。解构不成功右边的值会是undefined;不完全解构的话,左边的模式会匹配右边相对应的部分;等号右边不是数组会报错;解构赋值允许指定默认值,最后一个表达式之所以会报错,是因为

m

n

做默认值时,

n

还没有声明

var[a,[[b],c]] = [1,[[2],3]];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

let [ , , d] = ["A", "B", "C"];
console.log(d); // "C"

let [x,,y] = [1, 2, 3];
console.log(x); // 1
console.log(y); // 3

let [A,B, ...C]=['a']
console.log(A) //a
console.log(B) //undefined
console.log(C) //[]

let [o] = 1; //报错

let [m = 1, n = m] = [];     // m=1; n=1
let [m = 1, n = m] = [2];    // m=2; n=2
let [m = 1, n = m] = [1, 2]; // m=1; m=2
let [m =n, n = 1] = [];     // ReferenceError: n is not defined

4.2 对象的解构

与数组解构不同,对象解构变量必须与属性同名,才能取到正确的值。

let { a, b } = { a: 'aaa', b: 'bbb' };
console.log(a); 
console.log(b); 

let { c } = { d: 'ddd', e: 'eee' };
console.log(c);

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。 说白了就是,a是匹配的模式,b才是变量,真正被赋值的是b而不是模式a

let { a: b } = { a: 'aaa', b: 'bbb' };
console.log(b); 
console.log(a); 

对象的解构也可以指定默认值。

var {x = 3} = {x: undefined};
x // 3

var {x = 3} = {x: null};
x // null

上面代码中,属性

x

等于

null

,因为

null

undefined

不严格相等,所以是个有效的赋值,导致默认值

3

不会生效。

4.3 字符串的解构

对字符串进行解构后,得到的是类似于数组的对象

const [a, b, c, d, e] = 'hello';
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);

4.4 函数参数的解构

function fun([x, y]){
  return x + y;
}

add([2, 2]); // 4

函数fun的参数表面上是一个数组,但传入参数的那一刻,数组参数就被解构成变量x和y,当然函数参数也可以使用默认值。

function arr({x = 0, y = 0} = {}) {
  return [x, y];
}

arr({x: 3, y: 8}); // [3, 8]
arr({x: 3}); // [3, 0]
arr({}); // [0, 0]
arr(); // [0, 0]

4.5 数值和布尔值的解构

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象,数值和布尔值的包装对象都有

toString

属性,因此变量

s

都能取到值。由于

undefined

null

无法转为对象,所以对它们进行解构赋值,都会报错。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

4.6 圆括号问题

ES6 的规则:只要有可能导致解构的歧义,就不得使用圆括号。

// 全部报错
let [(a)] = [1];//变量声明语句
function f([(z)]) { return z; }//函数参数
({ p: a }) = { p: 42 };//赋值语句模式

可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是

p

,而不是

d

;第三行语句与第一行语句的性质一致。

4.7 注意点

(1)一个已经声明的变量用于解构赋值

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

// 正确的写法
let x;
({x} = {x: 1});

JavaScript 引擎会将

{x}

理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

(2)解构赋值允许等号左边的模式之中,不放置任何变量名。

({} = [true, false]);
({} = 'abc');
({} = []);

(3)可以对数组进行对象属性的解构。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

4.8 解构的作用

(1)交换变量的值

let x = 1;
let y = 2;
[x, y] = [y, x];

(2)函数参数的定义 (方便将一组参数和变量名对应起来)

function f({x, y, z}) { }
f({z: 3, y: 2, x: 1});

(3)从函数中返回多个值 (函数只能返回一个值,放在数值或对象中返回多个)

// 返回一个数组

function a() {
  return [1, 2, 3];
}
let [a, b, c] = a();
console.log(a());

// 返回一个对象

function b() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = b();
console.log(b());

(4)函数参数默认值(避免了在函数体内再书写)

jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {
  // ... do stuff
};

(5)输入模块的指定方法 (使输入语句非常清晰)

const { SourceMapConsumer, SourceNode } = require("source-map");

(6)遍历Map解构 (Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便)。

const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}

(7)提取JSON数据

let jsonData = {
  id: 2022,
  sex: "boy",
  data: [1, 2]
};

let { id, sex, data: number } = jsonData;

console.log(id, sex, number);

呼~,因为学习,文章拖了俩天才写完,不过总算是搞完了,本文一方面是加深自己对ES6的学习和提高知识的储备;另一方面也是希望帮助看到这篇文章的人学习更多的知识。今后也会不间断的更新关于前端的知识,大家一起共勉,一起进步,不足之处,还请指正。

想学习更多前端知识,关注博主,不迷路~~~~

下一篇:

未完待续。。。。。。

标签: javascript 前端 es6

本文转载自: https://blog.csdn.net/qq_53123067/article/details/124956925
版权归原作者 亦世凡华、 所有, 如有侵权,请联系我们删除。

“ECMAScript--》 ES6语法规范 ## Day1”的评论:

还没有评论