ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。
ES6 实际上是一个泛指,泛指 ES2015 及后续的版本。
目录
1. let 关键字和 const 关键字
let 关键字
-
作用:声明变量,用来代替
var
。let
声明的变量具备变量的基本特征。 -
语法:
let 变量名 = 值;
-
特点:
-
let
声明的变量不能重复声明。 -
let
声明的变量不会变量提升。 -
let
声明的变量不会再作为顶层全局的属性。 -
let
声明的变量在全局作用域和局部作用域的基础上新增了块级作用域。
-
块级作用域:
-
产生块级作用域的语法:
-
{}
语法{ let x = 1; console.log(x); // 1 } console.log(x); // ReferenceError: x is not defined
-
for
/while
循环结构for (let i = 0; i < 5; i++) { console.log(i); // 0, 1, 2, 3, 4 } console.log(i); // ReferenceError: i is not defined
-
if
/else
/switch
分支结构if (true) { let y = 2; console.log(y); // 2 } console.log(y); // ReferenceError: y is not defined
-
try
/catch
try { let z = 3; console.log(z); // 3 } catch (error) { console.log(error); } console.log(z); // ReferenceError: z is not defined
-
const 关键字
-
作用:用于定义常量,常量的特点是值不能修改。为了与变量区分,一般常量名一般采用全部大写(潜规则)。
-
特点:
-
const
声明的常量,不能重新赋值也不能重新声明。 -
全局变量不会作为顶层全局对象的属性值。
-
变量不会提升。
-
常量在全局作用域和局部作用域的基础上新增了块级作用域。
-
示例:
const PI = 3.14159;
console.log(PI); // 3.14159
PI = 3.14; // TypeError: Assignment to constant variable.
const obj = { name: '张三' };
console.log(obj.name); // 张三
obj.name = '李四'; // 常量对象的属性可以修改
console.log(obj.name); // 李四
2. 解构赋值
数组解构赋值
-
变量声明赋值:
let [a, b, c] = [1, 2, 3]; console.log(a, b, c); // 1, 2, 3
-
变量赋值:
[a, b, c] = [5, 6, 7]; console.log(a, b, c); // 5, 6, 7
-
解构赋值可以有默认值:
let [d, e, f = 300] = [433, 45]; console.log(d, e, f); // 433, 45, 300
-
数组解构可以是直接量也可以是变量:
let arr = [5, 6, 4, 3]; let [aa, bb, cc] = arr; console.log(aa, bb, cc); // 5, 6, 4
注意:
数组解构赋值本质是按照索引进行解构的,等号右边必须是数组或者伪数组(具有索引结构的),否则报错。
对象解构赋值
-
按照属性名进行匹配:
let { name: username, age: userage } = { name: 'anni', age: 100 }; console.log(username, userage); // anni, 100
-
属性名和变量名相同则可以简写:
let { a, b } = { a: 55, b: 'anni' }; console.log(a, b); // 55, anni
-
变量名可以有默认值:
let { c, d = 100 } = { c: 89 }; console.log(c, d); // 89, 100
注意:
-
一切皆对象,一切都可以作为对象解构赋值(除了
null
和undefined
)。 -
对象解构赋值不需要按照索引,只要有属性就可以。
解构赋值用于传参
-
数组的解构赋值:
function giao([a, b]) { console.log(a + b); } giao([100, 200]); // 300
-
对象解构赋值:
function woligiao({ name, age, address }) { console.log(name, age, address); } woligiao({ name: 'anni', age: 99, address: '上海' });
3. 字符串新增特性
模板字符串
-
定义:使用反引号声明的字符串,称为模板字符串。模板字符串适合内容较多,且需要嵌套很多变量的字符串。
-
示例:
let [msg1, msg2] = ['are you ok', 'i am fine']; let html = ` <ul> <li>${msg1}</li> <li>${msg2}</li> <li>${100 + 200}</li> </ul> `; console.log(html);
-
特性:
-
在模板字符串中换行会作为字符串内容。
-
模板字符串可以使用
${}
嵌入变量,表达式都可以嵌入到模板字符串中。 -
其他特性与单双引号字符串一致。
-
字符串实例新增方法
-
ES3 方法:
-
indexOf()
:返回参数在字符串中的位置。 -
lastIndexOf()
:返回参数在字符串中最后一次出现的位置。 -
toUpperCase()
:将字符串转换为大写。 -
toLowerCase()
:将字符串转换为小写。 -
slice()
:返回字符串的子字符串。 -
substring()
:返回字符串的子字符串。 -
substr()
:返回字符串的子字符串。 -
split()
:将字符串分割为数组。 -
charCodeAt()
:返回指定位置的字符的 Unicode 编码。
-
-
ES5 方法:
-
trim()
:去除字符串两边的空格,全是空格的字符串会转换为空字符串。
-
-
ES6+ 方法:
-
repeat()
:字符串重复。 -
includes()
:判断字符串中是否包含某个值,返回布尔值;第二个参数可以指定查找开始的位置。 -
startsWith()
:判断字符串是否以某个值开头,返回布尔值;第二个参数指定开始查找的位置。 -
endsWith()
:判断字符串是否以某个值结束,返回布尔值;第二个参数指定字符串查找的长度。 -
padStart()
:将字符串补充到指定的长度,在前面添加,第一个参数指定总长度,第二个参数指定填充内容(ES2017)。 -
padEnd()
:将指定字符串补充到指定长度,将填充内容添加到后面,第一个参数是指定总长度,第二个参数指定填充内容(ES2017)。 -
trimStart()
:删除字符串左边的空格(ES2019)。 -
trimEnd()
:删除字符串右边的空格(ES2019)。
-
4. 数值新增特性
新增二进制和八进制表示方法
-
示例:
let num1 = 0b101; // 二进制表示方法 let num2 = 0o101; // 八进制表示方法 console.log(num1); // 5 console.log(num2); // 65
Number 构造函数本身新增方法和属性
-
ES3 属性:
-
Number.MAX_VALUE
-
Number.MIN_VALUE
-
-
ES6 属性和方法:
-
Number.isNaN()
:同全局属性isNaN()
-
Number.isFinite()
:同全局函数isFinite()
-
Number.parseInt()
:同全局函数parseInt()
-
Number.parseFloat()
:同全局函数parseFloat()
-
Number.isInteger()
:判断是否是整数,返回布尔值。 -
Number.isSafeInteger()
:判断是否是安全整数。 -
Number.MAX_SAFE_INTEGER
:返回最大安全整数。 -
Number.MIN_SAFE_INTEGER
:返回最小安全整数。 -
Number.EPSILON
:返回 JS 的最小精度。
-
安全整数
-
定义:在
-2^53
到2^53
之间的整数称之为安全整数,不存在计算精度问题。超出该范围的数字计算存在精度问题。
5. Math 新增方法
ES3 属性方法
-
Math.PI
-
Math.abs()
-
Math.sqrt()
-
Math.pow()
-
Math.round()
-
Math.floor()
-
Math.ceil()
-
Math.random()
-
Math.max()
-
Math.min()
ES6 新增方法
-
Math.trunc()
:截取数字的整数部分,类似于parseInt()
。 -
Math.sign()
:参数是正数返回 1,参数是负数返回 -1,参数等于 0 返回 0,参数是NaN
返回NaN
。 -
Math.hypot()
:求所有参数的平方和的平方根。
6. 指数运算符
-
示例:
console.log(3 ** 3); // 27
7. 新增原始数据类型 BigInt
-
定义:如果要进行计算的数字超过安全整数的范围,还想保证精度的话,可以定义成
BigInt
类型。 -
示例:
let n1 = 100n; console.log(n1); // 100n console.log(typeof n1); // bigint // BigInt 类型数据只能与 BigInt 类型数据进行数学计算 console.log(n1 + 40n); // 140n // console.log(n1 * 3); // 报错 // BigInt 类型数据可以与 number 类型比较,自动类型转换 console.log(n1 === 100); // false console.log(n1 == 100); // true console.log(n1 > 40); // true console.log(n1 > 400); // false // 也有二进制方式、八进制方式、十六进制方式 let n2 = 0b101n; let n3 = 0o101n; let n4 = 0x101n; console.log(n2, n3, n4); // 5n, 65n, 257n
8. 函数新增特性
函数参数的默认值
-
示例:
function fun(name, age = 100) { console.log(name, age); } fun('姬发'); // 姬发 100 fun('姬发', 50); // 姬发 50
rest 参数
-
示例:
let getSum = (...nums) => { let sum = 0; nums.forEach(item => { sum += item; }); return sum; } console.log(getSum(4, 43, 5, 6, 7)); // 65
箭头函数
-
语法:
let fn = (name, age) => { console.log(`我叫${name},我今年${age}岁`); }; fn('gmy', '23'); //我叫gmy,我今年23岁
-
简略写法:
-
省略
()
的条件:只有一个参数,多个参数或者没有参数都不能省略。 -
省略
{}
的条件:函数体内只有一条返回值语句,省略{}
和return
。
-
-
示例:
let add = (a, b) => a + b; console.log(add(3, 4)); // 7 let greet = name => `你好,${name}!`; console.log(greet('张三')); // 你好,张三!
箭头函数的特点
-
箭头函数没有自己的
this
,会取上层作用域的this
;因此箭头函数中的this
与调用者无关,只与箭头函数声明的地方有关。 -
箭头函数没有
arguments
但是可以有rest
参数。 -
箭头函数不可以作为构造函数,
new
则报错。 -
箭头函数不能使用
yield
,无法创建生成器函数。
函数参数尾逗号(ES2017)
-
示例:
function fn(name, age, ) { console.log(name, age); } fn('安妮', 109); //安妮 109 fn('安妮', 108, ); //安妮 108
9. 数组的新特性
扩展运算符
-
示例:
function fun(a, b, c) { console.log(a, b, c, a + b + c); } var nums = [100, 200, 300, 250]; fun(nums); // 输出 [100, 200, 300, 250], undefined, undefined, 100, 200, 300, 250undefinedundefined fun(...nums); // 输出 100, 200, 300, 600
扩展运算符的应用场景
-
用于函数传参:
let arr = [123, 54, 65, 324]; console.log(Math.max(...arr)); // 324
-
复制数组:
let arr = [789, 534, 54, 234]; var arr2 = [...arr]; console.log(arr2); // [789, 534, 54, 234]
-
合并数组:
let arr1 = [43, 54, 56]; let arr2 = [24, 6, 234]; var arr3 = [...arr1, ...arr2]; console.log(arr3); // [43, 54, 56, 24, 6, 234]
-
把类数组转换为纯数组:
var arr = [...document.all]; var ary = [...'hello world']; console.log(ary); // ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
rest 元素
-
示例:
let [first, ...seconds] = [10, 20, 30, 40, 50]; console.log(first); // 10 console.log(seconds); // [20, 30, 40, 50]
Array 构造函数本身新增的方法
-
ES6 新增方法:
-
Array.from()
:把伪数组转换为纯数组。 -
Array.of()
:创建新数组,参数会作为数组中的元素,可以设置任意量的参数,基本可以用来代替Array()
和new Array()
。
-
Array 实例新增方法
-
ES3:
-
length
-
join()
-
slice()
-
push()
-
pop()
-
unshift()
-
shift()
-
concat()
-
splice()
-
reverse()
-
sort()
-
-
ES5:
-
indexOf()
-
lastIndexOf()
-
forEach()
-
filter()
-
map()
-
some()
-
every()
-
reduce()
-
reduceRight()
-
-
ES6:
-
find(callback)
:返回数组中第一个满足条件的元素,参数是回调函数,回调函数接受元素和索引,回调函数返回true
表示条件满足。 -
findIndex(callback)
:返回数组中第一个满足条件的参数的索引,参数是回调函数,回调函数接受元素和索引,回调函数返回true
表示条件满足。 -
fill(val [, start][, end])
:用于填充数组,把数组中的指定元素替换为val
,后两个参数不填则替换全部。 -
entries()
:返回由数组的索引和值构成的遍历器对象。 -
keys()
:返回由数组的索引组成的遍历器对象。 -
values()
:返回由数组的值组成的遍历器对象。 -
includes(val)
:判断数组中是否包含指定值,返回布尔值(可以判断NaN
)。 -
flat(num)
:用于拉平数组(把多维数组转换为一维数组),参数可以指定拉多少层,默认是 1,可以设置参数为Infinity
(拉平任意维数组)。 -
flatMap()
:先对数组map
处理再进行flat
操作,只能拉平一层。
-
10. 对象新特性
对象声明时候的简写
-
示例:
let [name, age, address, grade] = ['曹操', 32, '许昌', '魏国']; function getInfo() { console.log('getInfo'); } let obj = { name, age, address, grade, getInfo };
声明对象时方法的简写
-
示例:
let user = { name: '司马懿', age: 99, aoligei() { console.log('aoligei'); } };
属性名表达式
-
示例:
let prop = 'address'; let obj = { [prop]: '上海', [1 + 7]: '丑', 'user-name': '文丑', ['grade']: 66 }; console.log(obj); // { address: '上海', '8': '丑', 'user-name': '文丑', grade: 66 }
super 关键字
-
示例:
class Parent { constructor() { this.name = 'Parent'; } say() { console.log(`我是${this.name}`); } } class Child extends Parent { constructor() { super(); this.name = 'Child'; } say() { super.say(); console.log(`我是${this.name}`); } } let child = new Child(); child.say(); // 我是Parent 我是Child
对象的扩展运算符
-
示例:
let obj1 = { a: 1, b: 2 }; let obj2 = { b: 3, c: 4 }; let obj3 = { ...obj1, ...obj2 }; console.log(obj3); // { a: 1, b: 3, c: 4 }
对象的扩展运算符用于对象解构赋值
-
示例:
let { gdx, ...df } = { name: 534, gdx: 'ok', ok: 54, fls: 'fsdj' }; console.log(df); // { name: 534, ok: 54, fls: 'fsdj' }
Object 构造函数本身新增的方法
-
ES5 方法:
-
Object.create()
:创建一个对象,指定对象的原型。 -
Object.defineProperty()
:添加属性,并指定属性的特性。 -
Object.defineProperties()
:添加多个属性,并指定属性的特性。 -
Object.getOwnPropertyDescriptor()
:获取对象中属性的特性。
-
-
ES6 方法:
-
Object.is(arg1, arg2)
:用来判断参数是否相等,返回布尔值,与===
的区别是,+0
和-0
不相等,NaN
和NaN
相等。 -
Object.assign(target, source1, source2...)
:合并对象,把第二个参数开始合并到第一个参数,并返回第一个参数(用于:对象合并,对象复制,对象默认值)。 -
Object.keys(obj)
:返回对象obj
中所有属性名的数组集合。 -
Object.values(obj)
:返回obj
中所有属性值的数组集合。 -
Object.entries(obj)
:返回对象中所有的属性名和属性值组成的二维数组。 -
Object.fromEntries()
:Object.entries
的逆运算。 -
Object.getOwnPropertyDescriptors()
:获取对象中所有的特性信息。
-
Object 实例新增的属性
-
__proto__
属性(前后各两个下划线),用来读取或设置当前对象的原型对象。
11. Class 语法
使用 Class 定义类
-
示例:
class User { name = '安妮'; sex = '女'; say() { console.log(`我叫${this.name},我的性别是${this.sex}`); } } let u1 = new User(); u1.say(); // 我叫安妮,我的性别是女
类的语法特性
-
类的本质还是构造函数,
typeof
返回function
。 -
类只能用来实例化不能调用。
-
类中只能定义属性和方法,不能直接使用
this
(方法中才能写this
),不能写其他语句。 -
类中定义的属性会添加到实例的本身,类中定义的方法会添加到实例的原型上面。
类中定义构造器方法
-
示例:
class User { name = 'null'; age = 'null'; address = 'null'; constructor(name, age, address) { this.name = name; this.age = age; this.address = address; } say() { console.log(`我叫${this.name},今年${this.age}岁,住在${this.address}`); } } let u1 = new User('曹操', 99, '许昌'); u1.say(); // 我叫曹操,今年99岁,住在许昌
静态方法
-
示例:
class Foo { static classMethod() { return 'hello'; } } console.log(Foo.classMethod()); // hello
访问器属性
-
示例:
class Person { firstName = null; lastName = null; constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } get fullName() { return `${this.firstName}·${this.lastName}`; } set fullName(val) { if (val.includes('·')) { [this.firstName, this.lastName] = val.split('·'); } } } let p1 = new Person('张', '三'); console.log(p1.fullName); // 张·三 p1.fullName = '李·四'; console.log(p1.firstName); // 李 console.log(p1.lastName); // 四
实现继承
-
示例:
class Animal { color = null; weight = null; eat() { console.log('我是动物我会吃'); } } class Person extends Animal { name = null; say() { console.log(`我叫${this.name}, 我的肤色是${this.color}, 我的重量是${this.weight}`); } } let p1 = new Person(); p1.name = '刘备'; p1.color = '白'; p1.weight = 70; p1.say(); // 我叫刘备, 我的肤色是白, 我的重量是70 p1.eat(); // 我是动物我会吃
方法和属性的重写
-
示例:
class Animal { eat() { console.log('我是动物我会吃'); } } class Person extends Animal { eat() { console.log('我是人类我会吃'); } } let p1 = new Person(); p1.eat(); // 我是人类我会吃
super 关键字
-
示例:
class Person extends Animal { constructor(name, color, weight) { super(color, weight); this.name = name; } }
继承系统类(内置的构造函数)
-
示例:
class MyArray extends Array { constructor(...args) { super(...args); } } let arr = new MyArray(1, 2, 3); console.log(arr); // [1, 2, 3]
12. 新增元素数据类型 Symbol
-
定义:
Symbol
是 JavaScript 新增的一种原始类型数据,typeof
会返回symbol
。 -
创建:通过调用
Symbol()
可以创建Symbol
类型的数据,注意,Symbol
只能调用不能实例化。 -
特点:
-
每创建一个
Symbol
类型的数据,都是唯一的。 -
Symbol
类型的数据可以作为对象的属性名。
-
-
示例:
let s1 = Symbol('s1'); let s2 = Symbol('s2'); console.log(s1 === s2); // false let obj = { [s1]: 'value1', [s2]: 'value2' }; console.log(obj[s1]); // value1 console.log(obj[s2]); // value2
13. 新增数据类型 Set 和 Map
Set 数据类型
-
定义:
Set
是 ES6 新增的数据类型,跟数组类型相似,是值的集合,但是不能重复。 -
构造函数:
Set
函数可以接受一个数组(或者具有iterable
接口的其他数据结构)作为参数,用来初始化。 -
实例方法:
-
add()
:添加一个值。 -
delete()
:删除一个值。 -
has()
:判断是否包含某个值,返回布尔值。 -
clear()
:清空Set
所有值。 -
forEach()
:遍历。 -
keys()
:返回遍历器对象。 -
values()
:返回遍历器对象。 -
entries()
:返回遍历器对象。
-
-
属性:
-
size
:得到长度(类似于数组的length
)。
-
-
示例:
const s = new Set([1, 3, 4, 5]); console.log(s.size); // 4 s.add(6); console.log(s); // Set(5) {1, 3, 4, 5, 6} s.delete(3); console.log(s); // Set(4) {1, 4, 5, 6} console.log(s.has(4)); // true s.clear(); console.log(s); // Set(0) {}
WeakSet 数据类型
-
定义:
WeakSet
结构与Set
类似,也是不重复的值的集合,但是它与Set
有两个区别:-
WeakSet
成员只能是对象。 -
WeakSet
不可遍历。
-
-
构造函数:作为构造函数,
WeakSet
可以接受一个数组(或者其他可遍历对象)作为参数。该数组的所有成员,都会自动成为WeakSet
的实例对象的成员。 -
实例方法:
-
add(val)
-
delete(val)
-
has(val)
-
-
示例:
const ws = new WeakSet(); const obj1 = {}; const obj2 = {}; ws.add(obj1); ws.add(obj2); console.log(ws.has(obj1)); // true console.log(ws.has(obj2)); // true ws.delete(obj1); console.log(ws.has(obj1)); // false
Map 数据类型
-
定义:
Map
类型数据类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。 -
构造函数:任何具有
iterator
接口、且每个成员都是一个双元素的数据结构(数组和可遍历对象)都可以作为Map
构造函数的参数。 -
实例方法:
-
get(key)
:根据key
获取值。 -
set(key, val)
:根据key
设置值。 -
has(key)
:判断是否存在指定的key
。 -
delete(key)
:删除对应的key
和value
。 -
clear()
:清除所有的键值对。 -
keys()
:获取所有的key
组成的遍历器对象。 -
values()
:获取所有的value
组成的遍历器对象。 -
entries()
:获取所有的键值对组成的遍历器对象。 -
forEach(callback)
:用于遍历。
-
-
属性:
-
size
:获取键值对的数量。
-
-
示例:
let map = new Map([ [1, 2], ['ok', 'fine'], [{ name: 'anni' }, 1] ]); console.log(map.get(1)); // 2 console.log(map.get('ok')); // fine console.log(map.get({ name: 'anni' })); // 1 map.set('newKey', 'newValue'); console.log(map.has('newKey')); // true map.delete('newKey'); console.log(map.has('newKey')); // false map.clear(); console.log(map.size); // 0
WeakMap 数据类型
-
定义:
WeakMap
结构与Map
结构类似,也是用于生成键值对的集合,WeakMap
与Map
的区别有两点:-
WeakMap
只接受对象(所有的对象类型,除了原始类型)作为键名,不接受其他类型的值作为键名。 -
WeakMap
不可遍历。
-
-
构造函数:
WeakMap
可以使用set
方法添加成员,也可以接受一个数组作为构造函数的参数。 -
实例方法:
-
set(key, value)
-
get(key)
-
has(key)
-
delete(key)
-
-
示例:
const wm1 = new WeakMap(); const key = { foo: 1 }; wm1.set(key, 2); console.log(wm1.get(key)); // 2 const k1 = [1, 2, 3]; const k2 = [4, 5, 6]; const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]); console.log(wm2.get(k2)); // "bar"
14. Iterator 遍历器对象和可遍历对象
Iterator 遍历器对象
-
定义:
Iterator
(遍历器)是一种接口,为各种不同数据结构提供统一访问机制,任何数据只要部署Iterator
接口,就可以完成遍历操作。 -
特点:
-
每个
Iterator
(遍历器)都有一个next()
方法。 -
Iterator
遍历器内部存在一个指针,指针指向遍历器的第一个数据,调用next()
,会取出指针指向的数据,并且指针下移。 -
每一次调用
next()
方法,都会返回数据结构的当前成员的信息,具体来说,就是返回包含value
和done
两个属性的对象。其中value
属性是当前成员的值,done
属性是一个布尔值表示遍历是否结束。
-
-
示例:
var set = new Set([100, 200, 300, 400]); var setIterator = set.keys(); let res = null; do { res = setIterator.next(); if (res.value !== undefined) { console.log(res.value); } } while (!res.done);
Iterable 可遍历对象
-
定义:把部署了
Iterator
(遍历器对象)接口的数据结构称之为iterable
(可遍历对象)。 -
特点:
-
Iterator
接口部署在了数据结构的Symbol.iterator
属性上,换句话说,一个对象,只有具有Symbol.iterator
属性,且该属性指向一个返回Iterator
(遍历器对象)的函数,该对象就是iterable
(可遍历对象)。
-
-
原生实现了
Iterator
接口的类型(可遍历对象):-
Array
-
Set
-
Map
-
String
-
Arguments
-
NodeList
-
HTMLCollection
-
-
可遍历对象和类数组(伪数组):
-
类数组(伪数组):对象中有索引结构,有
length
属性,就是伪数组。 -
可遍历对象:部署了
Iterator
接口的对象,才是可遍历对象。
-
-
调用可遍历对象
Iterator
接口的场合:-
数组解构赋值
-
使用数组扩展运算符
-
Array.from()
-
for...of
遍历 -
Set
构造函数的参数 -
WeakSet
构造函数的参数 -
Map
构造函数的参数 -
WeakMap
构造函数的参数 -
Promise.all
-
Promise.race
-
-
示例:
var arr = ['red', 'green', 'blue']; for (let k of arr) { console.log(k); // red, green, blue }
15. 生成器 Generator
定义
-
生成器就是能创建遍历器的函数。
如何定义
-
示例:
function* gen() { yield 1; yield 2; yield 3; } let iter = gen(); console.log(iter.next().value); // 1 console.log(iter.next().value); // 2 console.log(iter.next().value); // 3 console.log(iter.next().value); // undefined
yield 关键字
-
特点:
-
yield
关键字返回一个值,遍历的时候每次得到的就是yield
的值。 -
调用
next()
,执行到yield
就会停止,下次调用next()
,执行到下一个yield
停止。 -
调用生成器函数无论里面有没有
return
,都会返回一个遍历器对象。
-
-
示例:
function* gener() { yield '值1'; yield '值2'; yield '值3'; yield '值4'; } let gen = gener(); console.log(gen.next().value); // 值1 console.log(gen.next().value); // 值2 console.log(gen.next().value); // 值3 console.log(gen.next().value); // 值4 console.log(gen.next().value); // undefined
return 可以终止生成器遍历
-
示例:
function* gen() { yield 1; yield 2; return 3; yield 4; // 这行代码不会执行 } let iter = gen(); console.log(iter.next().value); // 1 console.log(iter.next().value); // 2 console.log(iter.next().value); // 3 console.log(iter.next().value); // undefined
利用生成器对象部署 Iterator 接口
-
示例:
var obj = { name: '安妮', age: 89, address: '上海', [Symbol.iterator]: function* () { for (var k in obj) { yield [k, obj[k]]; } } }; for (let [key, value] of obj) { console.log(key, value); // name 安妮, age 89, address 上海 }
16. 模块(Module)
定义模块
-
示例:
-
module1.js
:export var firstName = 'anni'; export function say() { console.log('hello world'); }
-
module2.js
:var user = '典韦'; function skill() { console.log('奥利给'); } export default { user, skill };
-
模块导入
-
示例:
-
导入
module1.js
:import { firstName, say } from './module1.js'; console.log(firstName); // anni say(); // hello world
-
导入
module2.js
:import myMod from './module2.js'; console.log(myMod.user); // 典韦 myMod.skill(); // 奥利给
-
17. 新增的运算符(ES2020)
可选链运算符 ?.
-
定义:可选链运算符(
?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。 -
特点:
-
?.
操作符的功能类似于.
链式操作符,不同之处在于,在引用为空(null
或者undefined
)的情况下不会引起错误,该表达式短路返回值是undefined
。 -
与函数调用一起使用时,如果给定的函数不存在,则返回
undefined
。
-
-
示例:
const obj = { user: { name: 'anni' } }; console.log(obj.user?.name); // anni console.log(obj.user?.age); // undefined console.log(obj.getInfo?.()); // undefined
空值合并运算符 ??
-
定义:空值合并运算符(
??
)是一个逻辑操作符,当左侧的操作数为null
或者undefined
时,返回其右侧操作数,否则返回左侧操作数。 -
特点:
-
与逻辑或运算符(
||
)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用||
来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,''
或0
)时。
-
-
示例:
console.log(null ?? 2000); // 2000 console.log(undefined ?? 2000); // 2000 console.log(false ?? 2000); // false console.log(0 ?? 2000); // 0 console.log('' ?? 2000); // 空字符串 console.log(NaN ?? 2000); // NaN