ES6 入门学习

数组的扩展

Array.from()

Array.from 方法用于将两类对象转为真正的数组:

  • 类似数组的对象( array-like object)
  • 可遍历( iterable) 的对象( 包括ES6新增的数据结构Set和Map)

Array.from 还可以接受第二个参数, 作用类似于数组的 map 方法, 用来对每个
元素进行处理, 将处理后的值放入返回的数组。

1
Array.from(arrayLike, x => x * x);

Array.of()

Array.of 方法用于将一组值, 转换为数组

数组实例的copyWithin()

数组实例的 copyWithin 方法, 在当前数组内部, 将指定位置的成员复制到其他
位置( 会覆盖原有成员) , 然后返回当前数组。也就是说, 使用这个方法, 会修改
当前数组, 它接受三个参数:

  • target(必需) :从该位置开始替换数据
  • start(可选) :从该位置开始读取数据, 默认为0。如果为负值, 表示倒数
  • end(可选) :到该位置前停止读取数据, 默认等于数组长度。如果为负值,
    表示倒数

这三个参数都应该是数值, 如果不是, 会自动转为数值

1
2
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

上面代码表示将从3号位直到数组结束的成员( 4和5) , 复制到从0号位开始的位
置, 结果覆盖了原来的1和2

数组实例的find()和findIndex()

数组实例的 find 方法, 用于找出第一个符合条件的数组成员。它的参数是一个回
调函数, 所有数组成员依次执行该回调函数, 直到找出第一个返回值为 true 的成
员, 然后返回该成员。如果没有符合条件的成员, 则返回 undefined 。

1
2
3
4
5
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10

[1, 5, 10, 15].find((n) => n > 9)//10

find 方法的回调函数可以接受三个参数, 依次为当前的值、当前的
位置和原数组

数组实例的 findIndex 方法的用法与 find 方法非常类似, 返回第一个符合条件
的数组成员的位置, 如果所有成员都不符合条件, 则返回 -1

数组实例的fill()

fill 方法使用给定值, 填充一个数组。fill 方法还可以接受第二个和第三个参数, 用于指定填充的起始位置和结束位置。

1
2
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

数组实例的entries(), keys()和values()

ES6提供三个新的方法—— entries(), keys() 和 values() ——用于遍历数
组。它们都返回一个遍历器对象, 可以用 for…of 循环进行遍历, 唯一的区别是 keys() 是对键名的遍历、 values() 是对键值的遍历, entries() 是对键值对的遍历。

1
2
3
4
5
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"

数组实例的includes()

includes 方法返回一个布尔值, 表示某个数组是否包含给定
的值, 与字符串的 includes 方法类似。该方法属于ES7, 但Babel转码器已经支
持。

该方法的第二个参数表示搜索的起始位置, 默认为0。如果第二个参数为负数, 则
表示倒数的位置, 如果这时它大于数组长度( 比如第二个参数为-4, 但数组长度为
3) , 则会重置为从0开始。

1
2
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

函数的扩展

扩展运算符

扩展运算符( spread) 是三个点(… )。它好比rest参数的逆运算, 将一个数组转为用逗号分隔的参数序列。

1
2
console.log(...[1, 2, 3])
// 1 2 3

扩展运算符的应用

  1. 合并数组
1
2
3
4
5
6
7
8
9
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
  1. 与解构赋值结合
1
2
3
4
5
6
7
8
9
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list


const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]

如果将扩展运算符用于数组赋值, 只能放在参数的最后一位, 否则会报错。

  1. 字符串

扩展运算符还可以将字符串转为真正的数组。

1
2
[...'hello']
// [ "h", "e", "l", "l", "o" ]
  1. Map和Set结构, Generator函数

扩展运算符内部调用的是数据结构的Iterator接口, 因此只要具有Iterator接口的对
象, 都可以使用扩展运算符, 比如Map结构。

1
2
3
4
5
6
7
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);

let arr = [...map.keys()]; // [1, 2, 3]

函数绑定

函数绑定运算符是并排的两个双冒号(::) , 双冒号左边是一个对象, 右边是一个
函数。该运算符会自动将左边的对象, 作为上下文环境( 即this对象) , 绑定到右
边的函数上面。

1
2
3
4
5
6
7
foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

如果双冒号左边为空, 右边是一个对象的方法, 则等于将该方法绑定在该对象上
面。

1
2
3
4
5
6
7
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

let log = ::console.log;
// 等同于
var log = console.log.bind(console);

由于双冒号运算符返回的还是原对象, 因此可以采用链式写法。

1
2
3
4
let { find, html } = jake;
document.querySelectorAll("div.myClass")
::find("p")
::html("hahaha");

对象的扩展

属性的简洁表示法

ES6允许直接写入变量和函数, 作为对象的属性和方法。这样的书写更加简洁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var foo = 'bar';
var baz = {foo};
baz // {foo: "bar"}
// 等同于
var baz = {foo: foo};

function f(x, y) {
return {x, y};
}
// 等同于
function f(x, y) {
return {x: x, y: y};
} f
(1, 2) // Object {x: 1, y: 2}

var o = {
method() {
return "Hello!";
}
};
// 等同于
var o = {
method: function() {
return "Hello!";
}
};

如果某个方法的值是一个Generator函数, 前面需要加上星号。

1
2
3
4
5
var obj = {
* m(){
yield 'hello world';
}
};

Object.is()

ES5比较两个值是否相等, 只有两个运算符:相等运算符(== ) 和严格相等运算
符(=== ) 。它们都有缺点, 前者会自动转换数据类型, 后者的 NaN 不等于自
身, 以及 +0 等于 -0 。JavaScript缺乏一种运算, 在所有环境中, 只要两个值是
一样的, 它们就应该相等。

Object.is 用来比较两个值是否严格相等, 与严格比较运算符( ===) 的行为基本一致。不同之处只有两个:一是 +0 不等于 -0 , 二是 NaN 等于自身。

1
2
3
4
5
+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

Object.assign()

Object.assign 方法用于对象的合并, 将源对象( source) 的所有可枚举属性,
复制到目标对象( target) 。Object.assign 方法的第一个参数是目标对象, 后面的参数都是源对象。

1
2
3
4
5
6
7
var target = { a: 1 };

var source1 = { b: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

Object.assign 方法实行的是浅拷贝, 而不是深拷贝。也就是说, 如果源对象某
个属性的值是对象, 那么目标对象拷贝得到的是这个对象的引用。

Generator 函数

形式上, Generator函数是一个普通函数, 但是有两个特征。一是, function 关
键字与函数名之间有一个星号;二是, 函数体内部使用 yield 语句, 定义不同的
内部状态( yield语句在英语里的意思就是“产出”)。

yield语句

由于Generator函数返回的遍历器对象, 只有调用 next 方法才会遍历下一个内部
状态, 所以其实提供了一种可以暂停执行的函数。 yield 语句就是暂停标志。
遍历器对象的 next 方法的运行逻辑如下。

(1) 遇到 yield 语句, 就暂停执行后面的操作, 并将紧跟在 yield 后面的那个
表达式的值, 作为返回的对象的 value 属性值。

(2) 下一次调用 next 方法时, 再继续往下执行, 直到遇到下一个 yield 语
句。

(3) 如果没有再遇到新的 yield 语句, 就一直运行到函数结束, 直
到 return 语句为止, 并将 return 语句后面的表达式的值, 作为返回的对象
的 value 属性值。

(4) 如果该函数没有 return 语句, 则返回的对象的 value 属性值
为 undefined 。