# ES
# 参考文档
# let 和 const 命令
# let 命令
let
声明的变量只在声明位置的域内有效,不存在变量提升。let
暂时性死区。let
禁止重复声明。let
有块级作用域。
# 块级作用域
- ES6 加入的
# const 命令
const
声明一个只读的常量。一旦声明,常量的值就不能改变。const
一旦声明变量,就必须立即初始化,不能留到以后赋值。- 不存在变量提升。
- 不可重复声明。
- 常量的实质是一个存储地址的指针,它的不可变其实指的是这个地址不可以变。
# 变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
# 数组的解构赋值
实例:
let a = 1;
let b = 2;
let c = 3;
// 等同于下面这种写法
let [a, b, c] = [1, 2, 3];
2
3
4
5
如果解构不成功,变量的值就等于
undefined
。解构赋值允许指定默认值。
实例:
let [foo = true] = []; foo // true let [x, y = 'b'] = ['a']; // x='a', y='b' let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
1
2
3
4
5注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于 undefined,默认值才会生效。
let [x = 1] = [undefined]; x // 1 let [x = 1] = [null]; x // null
1
2
3
4
5如果一个数组成员是
null
,默认值就不会生效,因为null
不严格等于undefined
。支持不完全解构。
# 对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
如果解构失败,变量的值等于
undefined
。实例:
let {foo} = {bar: 'baz'}; foo // undefined
1
2上面代码中,等号右边的对象没有 foo 属性,所以变量 foo 取不到值,所以等于 undefined。
# 字符串的扩展
# 字符串的新增方法
includes()
:返回布尔值,表示是否找到了参数字符串。startsWith()
:返回布尔值,表示参数字符串是否在原字符串的头部。endsWith()
:返回布尔值,表示参数字符串是否在原字符串的尾部。repeat()
:返回一个新字符串,表示将原字符串重复 n 次。trimStart()
,去除头部空格。trimEnd()
,去除尾部空格。padStart()
用于头部补全。padEnd()
用于尾部补全。实例:
'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'
1
2
3
4
5padStart()
和padEnd()
一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
# 函数的扩展
# 默认值
实例
function Point(x = 0, y = 0) { this.x = x; this.y = y; } const p = new Point(); p // { x: 0, y: 0 }
1
2
3
4
5
6
7
# rest 参数
- 格式
...变量名
rest
参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。- 函数的
length
属性,不包括rest
参数。 - 实例:
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
2
3
4
5
6
7
8
9
10
11
# 箭头函数
格式:
var f = () => 5; // 等同于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var sum = function(num1, num2) { return num1 + num2; };
1
2
3
4
5
6
7
8
9当返回值是一个对象的时候,需要将代码块用圆括号包起来。
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
示例:
// 报错 let getTempItem = id => { id: id, name: "Temp" }; // 不报错 let getTempItem = id => ({ id: id, name: "Temp" });
1
2
3
4
5使用
this
的时候不使用箭头函数,因为它会将this
指向全局变量。
# 数组的扩展
# 扩展运算符
- 格式:
...
三个点 - 具有
Iterator
接口的对象,都可以使用扩展运算符,将它转换成真正的数组。
# includes 方法
Array.prototype.includes
方法返回一个布尔值,表示某个数组是否包含给定的值,
# 对象的扩展
# 对象的新增方法
# assign 方法
Object.assign()
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
实例:
const target = { a: 1, b: 1 }; const source1 = { b: 2, c: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
1
2
3
4
5
6
7如果只有一个参数,
Object.assign()
会直接返回该参数。浅拷贝。
# Set 和 Map 数据结构
# Map
size
set(k, v)
get(k)
has(k)
delete(k)
clear()
,清除所有成员,没有返回值。新建 Map 实例时,就指定了两个键
name
和title
。如果对同一个键多次赋值,后面的值将覆盖前面的值。
实例:
const m = new Map(); const o = {p: 'Hello World'}; m.set(o, 'content') m.get(o) // "content" m.has(o) // true m.delete(o) // true m.has(o) // false
1
2
3
4
5
6
7
8
9遍历方法
for ... of 实例:
const map = new Map([ ['F', 'no'], ['T', 'yes'], ]); for (let key of map.keys()) { console.log(key); } // "F" // "T"
1
2
3
4
5
6
7
8
9
10
# Promise 对象
# 三个状态
Promise 对象代表一个异步操作,有三种状态:
pending
(进行中)fulfilled
(已成功)rejected
(已失败)- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
# 两个参数
Promise构造函数接受一个函数作为参数。
该函数的两个参数分别是:
resolve
- 将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)。
- 在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
reject
- 将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected)。
- 在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
# 方法
finally()
,用于指定不管 Promise 对象最后状态如何,都会执行的操作。all()
,用于将多个 Promise 实例,包装成一个新的 Promise 实例。实例:
const p = Promise.all([p1, p2, p3]);
1p 的状态由 p1、p2、p3 决定,分成两种情况。
都成功才成功,只有 p1、p2、p3 的状态都变成fulfilled,p 的状态才会变成 fulfilled,此时 p1、p2、p3 的返回值组成一个数组,传递给 p 的回调函数。
一个失败即失败,只要 p1、p2、p3 之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 p 的回调函数。
race()
,谁先就是谁,只要 p1、p2、p3 之中有一个实例率先改变状态,p 的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。实例:
const p = Promise.race([p1, p2, p3]);
1
# Iterator 和 for...of 循环
# async 函数
async
函数返回一个 Promise 对象,可以使用 then
方法添加回调函数。当函数执行的时候,一旦遇到 await
就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
# 语法
返回一个 Promise 对象。
async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。
async function f() { return 'hello world'; } f().then(v => console.log(v)) // "hello world"
1
2
3
4
5
6实例:
async function getTitle(url) { let response = await fetch(url); let html = await response.text(); return html.match(/<title>([\s\S]+)<\/title>/i)[1]; } getTitle('https://tc39.github.io/ecma262/').then(console.log) // "ECMAScript 2017 Language Specification"
1
2
3
4
5
6
7上面代码中,函数
getTitle
内部有三个操作:抓取网页、取出文本、匹配页面标题。只有这三个操作全部完成,才会执行then
方法里面的console.log
。
# await 命令
await
命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。
# Class 基本语法
实例:
// ES 5 function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2); // ES 6 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Class 继承
# Module 语法
# export
格式:
// 第一种
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
// 第二种
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
2
3
4
5
6
7
8
9
10
// 这是方法的导出
// 报错
function f() {}
export f;
// 正确
export function f() {};
// 正确
function f() {}
export {f};
2
3
4
5
6
7
8
9
10
11
# import
import
命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口。
格式:
import { firstName, lastName, year } from './profile.js';
# export default
格式:
// 区别
// 第一组
export default function crc32() { // 输出
// ...
}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出
// ...
};
import {crc32} from 'crc32'; // 输入
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 讨论区
由于评论过多会影响页面最下方的导航,故将评论区做默认折叠处理。
点击查看评论区内容,渴望您的宝贵建议~
← JS