认识ES6
概述
ES6表示ECMAScript规范的第六版,正式名称为ECMAScript 2015,ECMAScript是由ECMA国际标准组织制定的一项脚本语言的标准规范化,引入了许多新特性和语法。
其中包括箭头函数、let和const声明、类、模板字符串、解构赋值、参数默认值、展开操作符、Promise等等。这些新的特性让JavaScript更加现代化、灵活和易于使用。
ES6可以在大多数现代浏览器中使用,也可以通过Babel等工具转换为ES5的语法以支持更旧的浏览器。除了浏览器之外,ES6还可以在Node.js环境下使用。总的来说,ES6已经成为现代JavaScript开发的标准,被广泛应用于各种前端和后端项目中。
ES6的目的是使JavaScript语言适应更复杂的应用,实现代码库之间的共享,并迭代维护新版本,成为企业级开发语言
关系
ECMAScript 是JavaScript语言的国际标准
JavaScript 是实现ECMAScript标准的脚本语言
关键字
let关键字
- let关键字声明的变量只有所处的块级作用域有效,而不是在整个函数作用域内有效
块级作用域是指花括号{}包含的代码块,比如for循环或if语句中的代码块。其作用场景有两个方面:
- 防止代码块内层变量覆盖外层变量
javascript
<script>
if (true) {
let a = 10;
console.log(a); //输出结果:10
}
console.log(a); //报错,a未定义
</script>
这段代码中使用了let关键字来声明变量a。let关键字声明的变量具有块级作用域,即只在当前代码块内有效。在这个例子中,a只在if语句的代码块中定义,因此在代码块外部访问变量a时会报错,提示变量未定义。
具体地说,当执行到console.log(a)的时候,因为a只存在于if语句的块级作用域中,所以在块级作用域外部并不存在变量a,导致此处的console.log(a)执行时出现了引用错误
- 防止循环变量变成全局变量
javascript
<script>
for (let i = 0; i < 2; i++) {}
console.log(i); //报错,i未定义
</script>
这段代码使用了let关键字来声明变量i。在JavaScript中,let关键字声明的变量具有块级作用域,因此在代码块外部无法访问该变量。在这个例子中,for循环中的变量i只存在于for循环的代码块中,当循环结束后,变量i的作用域也就结束了,外部无法再访问该变量。因此,在代码块外部访问变量i时,会报错提示变量未定义。
具体来说,当执行到console.log(i)的时候,因为i只存在于for循环的块级作用域中,所以在块级作用域外部并不存在变量i,导致此处的console.log(i)执行时出现了引用错误。
提示:let关键字的好处是避免变量污染全局作用域,提高代码可维护性,也可以避免var声明变量时存在的变量提升问题,即在变量声明之前使用变量会导致不可预测的结果。
arcade
function foo() {
let x = 1; //只在 example 函数内部有效
if (true) {
let x = 2; // 不同于外部的 x,只在 if 语句块内有效
console.log(x); //输出2
}
console.log(x); //输出1
}
在if语句的块级作用域内声明的变量x只在该作用域内有效,不会影响到外部作用域的变量x,因此输出结果为2和1。
- let关键字声明的变量不存在变量提升
在JavaScript中使用var关键字声明的变量时,变量可以先使用后声明,即变量的声明语句会被提前至作用域的顶部,但是变量的赋值语句仍然保留在原来的位置。这种现象称为变量提升。
而使用let关键字声明的变量则不会发生变量提升,变量的声明和赋值必须在同一代码块内完成,否则会报错。这意味着,在使用let关键字声明变量之前,该变量的上下文中必须不存在对该变量的引用或调用,否则会抛出ReferenceError异常。
下面是一个简单的案例:
arcade
<script>
console.log(count); // 报错:count未定义
let count = 0;
</script>
在上述例子中,使用let关键字声明了一个名为count的变量,并将其初始化为0。但是,在第一行调用count时,由于使用let关键字声明的变量不存在变量提升,count变量未被定义,代码会抛出引用错误。
- let关键字声明的变量具有暂时性死区特性
暂时性死区是指在代码块中(例如,函数、循环或块语句中)使用let或const声明变量时,变量在声明前无法被访问。在该变量声明之前的任何访问都将导致"ReferenceError"。
具体来说只要块级作用域内存在let命令,它所声明的变量就"绑定"(binding)了这个区域,不再受外部的影响。这意味着在变量声明前,该变量是不能被访问或调用的。
以下是一个例子,展示了let关键字声明的变量具有暂时性死区特性:
abnf
<script>
let x = 10;
if (true) {
console.log(x); // 报错:x未定义
let x = 20;
}
<script>
在这个例子中,变量x被定义为10,并在if语句中使用let关键字重新声明并初始化为20。但是,在if语句的块级作用域内,x被绑定了该区域,因此变量x在声明之前被访问会导致引用错误。这就是暂时性死区的特性
const关键字
- const关键字声明常量的只有所处的块级作用域有效 ,而不是在整个函数作用域内有效
下面是一个简单的例子,演示了使用const关键字声明常量的作用域仅限于所在的块级作用域(即大括号内)。
javascript
function example() {
const a = 1;
if (true) {
const a = 2;
console.log(a); // 输出2
}
console.log(a); // 输出1
}
example();
在这个例子中,我们在函数作用域内声明了一个常量a
,并在if语句的块级作用域内重新声明a
。由于const声明的常量的作用域仅限于所在的块级作用域(即大括号内),所以第一个console.log
语句输出2
,而第二个console.log
语句输出1
。
- const关键字声明常量时必须赋值
使用 const
声明常量时必须同时进行赋值,否则会抛出一个 SyntaxError 错误。这是因为 const
声明的变量是常量,一旦被声明,就不能再被修改。以下是一个使用 const
声明常量并赋值的例子:
arcade
const PI = 3.14159;
console.log(PI); //输出 3.14159
- const关键字声明常量赋值后常量的值不能修改
使用 const
声明的常量的值不能被修改。以下是一个简单的案例:
const PI = 3.14159;
PI = 3.14; // 尝试修改常量的值
console.log(PI); // 会抛出一个 TypeError 错误
在上述代码中,我们尝试将 PI
的值修改为 3.14
,但运行该代码时会抛出一个 TypeError
错误,因为我们不能修改 const
声明的常量的值。
提示:var
、let
、const关键字之间的区别:都是
用于声明变量或常量,其中 var
是 ES5 中声明变量的方式,而 let
和 const
是 ES6 中引入的声明变量和常量的方式。 var
和 let
声明的变量可以被重新赋值,而 const
声明的常量不可被重新赋值。
解构赋值
概述
解构表示对数据结构进行分解,赋值是指将某一数值赋给变量的过程
优点是编写的代码简洁易读、语义清晰、方便从数组或对象中提取值
数组的解构赋值
数组的解构赋值就是将数组中的值提取出来,赋给另外的变量
数组的解构赋值是一种方便的方式,可以让我们从数组中获取单个值或多个值,然后将它们赋值给变量。它的基本语法如下:
javascript
let arr = [1, 2, 3, 4];
let [a, b, c, d] = arr;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // 4
//注意在浏览器控制台中输出上述代码的结果,有可能会报错,可以把let关键字去掉再运行
在上面的例子中,我们定义了一个数组 arr
,然后使用数组解构赋值的方式将数组中的元素赋值给变量 a
、b
、c
、d
。这样我们就可以通过变量来获取数组中的元素了。
对象的解构赋值
对象的解构赋值允许使用变量的名字匹配对象的属性,如果匹配成功就将对象中属性的值赋给变量
对象的解构赋值是一种方便的方式,可以让我们从对象中获取单个属性或多个属性,并将它们赋值给变量。它的基本语法如下:
javascript
let obj = { x: 1, y: 2 };
let { x, y } = obj;
console.log(x); // 1
console.log(y); // 2
在上面的例子中,我们定义了一个对象 obj
,然后使用对象解构赋值的方式将对象中的属性赋值给变量 x
、y
。这样我们就可以通过变量来获取对象中的属性了。
箭头函数
概述
箭头函数是ES6中引入的一种新的函数表达式,它的语法更加简洁,同时还具有一些特殊的功能
用于简化函数的定义语法,有自已的特殊语法,接收一定数量的参数,并在其封闭的作用域的上下文(即定义的函数或其他代码)中操作
语法
基本定义语法:
javascript
() => { }
上述语法中
() => { } 是 ES6 中的箭头函数语法,它表示一个没有参数的箭头函数,并且函数体为空。具体来说,箭头函数是一种更加简洁的函数表达式,可以用一个箭头(=>
)连接函数参数和函数体。例如:
javascript
// 常规函数表达式
function add(a, b) {
return a + b;
}
// 箭头函数表达式
const add = (a, b) => a + b;
特点
-
箭头函数是匿名函数,因此需要通过变量或常量来引用函数。例如:
javascript// 声明一个箭头函数并赋值给变量 add const add = (a, b) => a + b; // 使用 add 函数计算 1 + 2 的值 const result = add(1, 2); // 3
-
箭头函数可以省略函数体中的花括号
{ }
,如果函数体只有一条语句,那么可以直接返回这条语句的值。例如:javascript// 等价于 function (a, b) { return a + b; } const add = (a, b) => a + b; // 等价于 function (num) { return num % 2 === 0; } const isEven = num => num % 2 === 0;
-
箭头函数的参数列表可以省略小括号
()
,但是只有当参数个数为1时可以省略。例如:
javascript
// 等价于 function (num) { return num * num; }
const square = num => num * num;
// 等价于 function () { console.log('Hello, world!'); }
const logHello = () => console.log('Hello, world!');
-
箭头函数没有自己的
this
值,它会继承外层作用域的this
值,因此在箭头函数中使用this
时,它会指向外层作用域的this
,而不是箭头函数自己的this
。例如:javascriptconst obj = { name: 'Alice', greet: function() { setTimeout(() => { console.log(`Hello, ${this.name}!`); }, 1000); }, }; obj.greet(); // "Hello, Alice!" (1秒钟后输出)
在上面的代码中,我们定义了一个对象
obj
,它有一个名为greet
的方法,方法中使用了箭头函数来打印一条欢迎语句。由于箭头函数继承了greet
方法的this
值,因此在箭头函数中使用this.name
时,它会指向obj
的name
属性,即输出Hello, Alice!
扩展:在ES6之前,JavaScript中的关键字this指向的对象是在运行时基于函数的执行环境绑定的,在全局函数中,关键字this指向的是window;当函数被作为某个对象的方法调用时,this关键字指向那个对象
剩余参数
概述
在 JavaScript 中,剩余参数(Rest Parameters)是一种特殊的函数参数,它允许我们在函数定义中传入任意数量的参数,而这些参数都会被自动组织成一个数组,并作为剩余参数传递给该函数。在函数体中,我们可以像处理普通数组一样使用剩余参数,也就是通过下标来获取数组元素,或者使用数组的一些方法对其进行操作。
语法
javascript
function funcName(...args) {
// function body
}
上述代码中的 ...args
表示任意数量的参数,它们会被组织成一个数组 args
。可以通过数组下标 args[0]
、args[1]
等来引用这些参数。
除了在函数定义时使用剩余参数外,我们还可以在调用函数时使用剩余参数来传入一个数组,这时候需要在数组前面加上三个点 ...
,以表示将该数组转换成一系列的参数。例如:
javascript
function funcName(arg1, arg2, ...restArgs) {
// function body
}
let arr = [1, 2, 3, 4, 5];
funcName(...arr);
上述代码中的 ...restArgs
表示剩余参数,它会包含数组 arr
中除了前两个元素以外的所有元素,也就是 3、4、5。由于我们在调用函数时使用了 ...arr
,因此这个数组会被转换成一系列的参数,即 arg1
为 1,arg2
为 2,restArgs
则为剩余的参数。
组合使用
剩余参数和解构赋值可以很好地组合在一起使用,以便更方便地访问剩余参数中的元素。
例如,我们可以在函数定义中使用解构赋值来获取剩余参数中的第一个和第二个元素,然后在函数体内对它们进行操作。示例代码如下:
javascript
function funcName(...[first, second, ...rest]) {
console.log("first:", first); // 输出第一个元素
console.log("second:", second); // 输出第二个元素
console.log("rest:", rest); // 输出剩余的元素
}
funcName(1, 2, 3, 4, 5);
在上述代码中,剩余参数 rest
包含了除了前两个参数以外的所有元素,而我们通过解构赋值分别获取了剩余参数中的第一个和第二个元素,分别赋值给了变量 first
和 second
。
这样,我们就可以在函数体内直接使用变量 first
和 second
来操作这两个元素,而无需通过下标来访问它们。同时,函数调用代码也变得更加简洁,只需要传入一系列的参数即可,无需手动创建一个数组。
项目
下面是一个利用关键字、解构赋值、箭头函数和剩余参数来实现一个简单的项目的示例。该项目可以将用户输入的一组数字求和,并在控制台输出结果。
javascript
// 定义求和函数
const sum = (...numbers) => {
let total = 0; //使用关键字 `let` 声明变量 `total`
for (let number of numbers) { //使用 `for...of` 循环遍历可迭代对象 `numbers` 中的元素。
total += number; //累加语句,将 `number` 的值加到 `total` 中
}
return total; //函数返回值,将计算得到的 `total` 作为函数返回值
}; //箭头函数的定义方式,使用剩余参数语法 `...` 来接收任意数量的参数。
// 监听用户输入
const inputValues = () => {
let input = prompt("请输入一组数字,用逗号分隔:"); //使用 `prompt` 方法显示一个提示框,并接收用户输入的一组数字。
let values = input.split(",").map((value) => parseInt(value.trim())); //使用 `split` 方法将用户输入的数字字符串按照逗号分隔成为一个数组,然后使用 `map` 方法对数组中的每个元素进行处理,去掉空格并将其转换为整数类型。
let total = sum(...values); 。。使用剩余参数语法 `...`,将数组 `values` 展开成为一个个数字拆分,作为参数传递给 `sum` 函数,并将计算结果赋值给变量 `total`
console.log(`结果:${total}`); //:使用模板字符串的语法,将计算得到的结果输出到控制台中。
10. `inputValues();`:调用函数开始监听用户输入并计算结果。
};
inputValues(); // 调用函数开始监听输入并计算结果
上述代码中,我们首先定义了一个求和函数 sum
,使用了箭头函数和剩余参数的特性,用于接收用户输入的一组数字,并计算它们的和。接下来,我们定义了一个监听用户输入的函数 inputValues
,其中使用了关键字 let
、解构赋值和数组的 map
方法,将用户输入的一组逗号分隔的数字字符串转换成了数组,然后将数组传递给 sum
函数计算结果。最后,我们在函数内部使用了 console.log
方法将结果输出到控制台。
在调用 inputValues
函数时,用户将会收到一个提示框,要求输入一组数字,用逗号分隔。用户输入完成后,我们将监听到输入并将其转换成数字数组,然后求和,并将结果输出到控制台。