ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

1. 定义变量

1.1 let

ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
let 具有几个特点如下

1. 不存在变量提升
let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。

1
2
3
4
5
console.log(foo); // 输出undefined
console.log(bar); // 报错ReferenceError

var foo = 2;
let bar = 2;

上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

2. 代码块内有效

1
2
3
4
5
6
7
{
let a = 10;
var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效

for循环的计数器,就很合适使用let命令。

1
2
3
4
5
6
7
8
9
10
11
12
for(let i = 0;i<10;i++){
setTimeout(function() {
console.log(i);
},0)
}
// 会输出0-9
for(var i = 0;i<10;i++){
setTimeout(function() {
console.log(i);
},0)
}
// 会输出10个10

3. 暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

1
2
3
4
5
6
var tmp = 123;

if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}

但是如果代码块内没有声明,还是会去上一层找变量

1
2
3
4
5
let tmp = 123;

if (true) {
console.log(tmp);// 123
}

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

4. 不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 报错
function () {
let a = 10;
var a = 1;
}

// 报错
function () {
let a = 10;
let a = 1;
}
function func(arg) {
let arg; // 报错
}

function func(arg) {
{
let arg; // 不报错
}
}

1.2 块级作用域

  • 场景一
    内层变量可能会覆盖外层变量。
1
2
3
4
5
6
7
var tmp = new Date();

function f() {
console.log(tmp);
}

f() // Tue Feb 19 2019 10:31:10 GMT+0800 (中国标准时间)
1
2
3
4
5
6
7
8
9
10
var tmp = new Date();

function f() {
console.log(tmp);
if (false) {
var tmp = "hello world";
}
}

f(); // undefined

上面代码中,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

  • 场景二
    用来计数的循环变量泄露为全局变量。
1
2
3
4
5
6
7
var s = 'hello';

for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}

console.log(i); // 5
1
2
3
4
5
6
7
var s = 'hello';

for (let i = 0; i < s.length; i++) {
console.log(s[i]);
}

console.log(i); //i is not defined

1.3 const

const声明一个只读的常量。一旦声明,常量的值就不能改变。

1. 不可变(地址不可变)

  • 对于简单数据类型来说const不可以改变

    1
    2
    3
    4
    5
    const PI = 3.1415;
    PI // 3.1415

    PI = 3;
    // TypeError: Assignment to constant variable.
  • 对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。

    1
    2
    3
    4
    5
    6
    7
    const foo = {};
    foo.prop = 123;

    foo.prop
    // 123

    foo = {}; // TypeError: "foo" is read-only

上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。

同理对于数组类型

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

2. 声明必赋值
对于const来说,只声明不赋值,就会报错。

1
2
const foo;
// SyntaxError: Missing initializer in const declaration

1.4 顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在Node指的是global对象。ES5之中,顶层对象的属性与全局变量是等价的。

1
2
3
4
5
6
7
8
window.a = 1;
a // 1

var a = 2;
window.a // 2

let b = 1;
window.b // undefined
  • 一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;
  • 另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性

2. 解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

2.1 数组解构

以前,为变量赋值,只能直接指定值

1
2
3
var a = 1;
var b = 2;
var c = 3;

ES6允许写成下面这样。

1
var [a, b, c] = [1, 2, 3];

这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

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
27
28
29
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

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

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

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

let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4

对于Set结构,也可以使用数组的解构赋值。

1
2
let [x, y, z] = new Set(["a", "b", "c"]);
x // "a"

2.2 默认值

解构赋值允许指定默认值。

1
2
[x, y = 'b'] = ['a']; // x='a', y='b'
[x, y = 'b'] = ['a', undefined]; // x='a', y='b'

如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined。

1
2
3
4
5
var [x = 1] = [undefined];
x // 1

var [x = 1] = [null];
x // null

如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

1
2
3
4
5
function f() {
console.log('aaa');
}

let [x = f()] = [1];

因为x能取到值,所以函数f根本不会执行

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

1
2
3
4
let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError

2.3 对象的解构赋值

解构不仅可以用于数组,还可以用于对象。

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

  • 数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
  • 不将大括号写在行首,避免JavaScript将其解释为代码块(在大括号两侧加()解决)
    如果变量名与属性名不一致
1
2
3
4
5
6
7
var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

如果变量名与属性名一致

1
2
3
var { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

变量不能重新声明

1
2
3
4
5
let foo;
let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"

let baz;
let {bar: baz} = {bar: 1}; // SyntaxError: Duplicate declaration "baz"

嵌套赋值

1
2
3
4
5
6
7
let obj = {};
let arr = [];

({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

obj // {prop:123}
arr // [true]

2.4 字符串的解构赋值

字符串被转换成了一个类似数组的对象,然后再进行解构
同理,任何对象进行解构赋值都是转换成一个类似数组的对象,再进行赋值

1
2
3
4
5
6
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

3 字符串扩展

3.1 字符串是否包含

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。

includes()可以直接放到if中

1
2
3
4
5
6
7
8
9
10
var s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true


s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

3.2 字符串重复

repeat方法返回一个新字符串,表示将原字符串重复n次。

1
2
3
4
5
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""

`

参数如果是小数,会被取整

1
'na'.repeat(2.9) // "nana"

如果repeat的参数是负数或者Infinity,会报错。

1
2
3
4
'na'.repeat(Infinity)
// RangeError
'na'.repeat(-1)
// RangeError

如果参数是0到-1之间的小数,则等同于0,这是因为会先进行取整运算。0到-1之间的小数,取整以后等于-0,repeat视同为0。

1
'na'.repeat(-0.9) // ""

参数NaN等同于0。

1
'na'.repeat(NaN) // ""

如果repeat的参数是字符串,则会先转换成数字。

1
2
'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"

3.3 字符串补全

ES7推出了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart用于头部补全,padEnd用于尾部补全。
第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。
如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

1
2
3
4
5
6
7
8
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'

如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。

1
2
'abc'.padStart(10, '0123456789')
// '0123456abc'

如果省略第二个参数,则会用空格补全长度。

1
2
'x'.padStart(4) // '   x'
'x'.padEnd(4) // 'x '

3.3 模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。

1
2
3
4
5
6
7
8
9
10
11
12
var x = 1;
var y = 2;

`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"

`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"

var obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// 3

模板字符串之中还能调用函数。

1
2
3
4
5
6
function fn() {
return "Hello World";
}

`foo ${fn()} bar`
// foo Hello World bar

4 数组的扩展

4.1 Iterator接口

  • Iterator接口的目的就是为所有数据结构提供一种统一访问的机制,用for…of实现。

  • 一个数据结构只要有Symbol.iterator属性,就可以认为是“可遍历的”

  • 原型部署了Iterator接口的数据结构有三种,具体包含四种,分别是

    • 数组
    • 类似数组的对象
    • Set
    • Map
  • 字符串是一个类似数组的对象,也原生具有Iterator接口。

  • 还有几个别的场合。

    • 解构赋值
    • 扩展运算符(…)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//创建一个构造函数
function Obj(value){
this.value=value;
this.nnext=null;
}
// 添加iterator接口
Obj.prototype[Symbol.iterator]=function(){
var iterator={next:next};
var self=this;
function next(){
if(self){
var value=self.value;
var done=self.next===null;
self=self.next;
return {
value:value,
done:done
};
}else{
return {done:true};
}
}
return iterator;
}

一个为对象添加Iterator接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let obj = {
data: [ 'hello', 'world' ],
[Symbol.iterator]() {
const self = this;
let index = 0;
return {
next() {
if (index < self.data.length) {
return {
value: self.data[index++],
done: false
};
} else {
return { value: undefined, done: true };
}
}
};
}
};

4.2 转换数组

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

1
2
3
4
5
6
7
8
9
10
11
12
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组。

1
2
3
4
5
6
7
8
9
10
11
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});

// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}

用扩展运算符也可以

1
2
3
4
5
6
7
// arguments对象
function foo() {
var args = [...arguments];
}

// NodeList对象
[...document.querySelectorAll('div')]

(…)和Array.from区别

只要是部署了Iterator接口的数据结构,Array.from都能将其转为数组。

扩展运算符(...)也可以将某些数据结构转为数组。

  • 扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。
  • 任何有length属性的对象,都可以通过Array.from方法转为数组
1
2
Array.from({ length: 3 });
// [ undefined, undefined, undefined ]

Array.from处理数据

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

1
2
3
4
5
6
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]

下面的例子是取出一组DOM节点的文本内容。

1
2
3
4
5
6
7
let spans = document.querySelectorAll('span.name');

// map()
let names1 = Array.prototype.map.call(spans, s => s.textContent);

// Array.from()
let names2 = Array.from(spans, s => s.textContent)

字符串长度

Array.from()的另一个应用是,将字符串转为数组,然后返回字符串的长度。因为它能正确处理各种Unicode字符,可以避免JavaScript将大于\uFFFF的Unicode字符,算作两个字符的bug。

1
2
3
function countSymbols(string) {
return Array.from(string).length;
}

4.3 一组值转换为数组

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

1
2
3
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

Array()和Array.of

  • Array方法没有参数、一个参数、三个参数时,返回结果都不一样。
  • 只有当参数个数不少于2个时,Array()才会返回由参数组成的新数组。
  • 参数个数只有一个时,实际上是指定数组的长度。
    1
    2
    3
    Array() // []
    Array(3) // [, , ,]
    Array(3, 11, 8) // [3, 11, 8]

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

1
2
3
4
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

4.4 成员复制

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

1
Array.prototype.copyWithin(target, start = 0, end = this.length)

它接受三个参数。

  • 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。

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
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]

// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5}
// Array.from({length: 5, 3: 1})
// [undefined, undefined, undefined, 1, undefined]
// 第3个位置是1,当道第0位[1, undefined, undefined, 1, undefined]
// call改变this是对象,所以返回的也是对象{0: 1, 3: 1, length: 5}

// 将2号位到数组结束,复制到0号位
var i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]

// 对于没有部署TypedArray的copyWithin方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]

4.5 数组查找

find()

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

找出数组中第一个小于0的成员。

1
2
[1, 4, -5, 10].find((n) => n < 0)
// -5

find方法的回调函数可以接受三个参数,依次为

  • 当前的值
  • 当前的位置
  • 原数组。

找出第一个大于9的成员

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

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

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

4.6 填充数组

fill方法使用给定值,填充一个数组。

  • 对于空数组,fill方法用于空数组的初始化。
  • 对于数组中已有的元素,会被全部抹去。
1
2
3
4
5
['a', 'b', 'c'].fill(7)
// [7, 7, 7]

new Array(3).fill(7)
// [7, 7, 7]

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

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

4.6 数组便利

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

  • keys()是对键名的遍历
  • values()是对键值的遍历
  • entries()是对键值对的遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'

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

4.7 数组包含

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。

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

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

1
2
3
4
5
6
7
8
[3, 2, 1].includes(3, 0); 
// true
[3, 2, 1].includes(3, 1);
// false
[1, 2, 3].includes(3, 3);
// false
[1, 2, 3].includes(3, -1);
// true

4.8 回顾ES5中数组方法

  • 2个索引方法:indexOf() 和 lastIndexOf();
  • 5个迭代方法:forEach()、map()、filter()、some()、every();
  • 2个归并方法:reduce()、reduceRight();

索引方法

索引方法包含indexOf()和lastIndexOf()两个方法,这两个方法都接收两个参数,

  • 第一个参数是要查找的项,
  • 第二个参数是查找起点位置的索引,该参数可选,如果缺省或是格式不正确,那么默认为0。两个方法都返回查找项在数组中的位置,如果没有找到,那么返回-1
    indexOf():该方法从数组的开头开始向后查找。
    1
    2
    3
    4
    5
    var dataArray = [1, 7, 5, 7, 1, 3];
    console.log(dataArray.indexOf(7)); // 1 从第一项开始查找
    console.log(dataArray.indexOf(7, 's')); // 1 格式不正确, 从第一项开始查找
    console.log(dataArray.indexOf(7, 2)); // 3   从第三个项之后开始查找
    console.log(dataArray.indexOf (2)); // -1 未找到, 返回-1

lastIndexOf(): 该方法从数组的末尾开始向前查找

1
2
3
4
5
var dataArray = [1, 7, 5, 7, 1, 3];
console.log(dataArray.lastIndexOf (7)); // 3 从末尾第一项开始查找
console.log(dataArray.lastIndexOf (7, 's')); // 3 格式不正确, 从末尾第一项开始查找
console.log(dataArray.lastIndexOf (7, 2)); // 1   从末尾第三项往前查找
console.log(dataArray.lastIndexOf ('4')); // -1 未找到, 返回-1

迭代方法

这些方法都接收两个参数,

  • 第一个参数是一个函数,他接收三个参数,
    • 数组当前项的值
    • 当前项在数组中的索引
    • 数组对象本身。
  • 第二个参数是执行第一个函数参数的作用域对象,也就是上面说的函数中this所指向的值。
  • 注意,这几种方法都不会改变原数组。

every()
该方法对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回true。

1
2
3
4
5
6
7
8
9
var dataArray = [1, 7, 5, 7, 1, 3];
var result = dataArray.every(function(item,index,arry){
return item>1;
})
console.log(result)//false
var result = dataArray.every(function(item,index,arry){
return item>0;
})
console.log(result)//true

some()
该方法对数组中的每一项运行给定函数,如果该函数对任何一项返回 true,则返回true。
some方法会在数组中任一项执行函数返回true之后,不在进行循环。

1
2
3
4
5
var dataArray = [1, 7, 5, 7, 1, 3];
var result = dataArray.some(function(item,index,arry){
return item > 5;
})
console.log(result)//true

filter()
该方法对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。利用这个方法可对数组元素进行过滤筛选。

1
2
3
4
5
var dataArray = [1, 7, 5, 7, 1, 3];
var result = dataArray.filter(function(item,index,arry){
return item > 3;
})
console.log(result)//[7, 5, 7]

map()
该方法对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

我们为数组中的每一项乘以3,返回每一项相乘之后的数组。

1
2
3
4
5
var dataArray = [1, 7, 5, 7, 1, 3];
var result = dataArray.map(function(item,index,arry){
return item* 3;
})
console.log(result) // [3, 21, 15, 21, 3, 9]

forEach()
该方法对数组中的每一项运行给定函数。这个方法没有返回值。这个方法其实就是遍历循环,和for循环没有太大差别。

1
2
3
4
5
6
7
8
9
10
var dataArray = [1, 7, 5, 7, 1, 3];
dataArray.forEach(function(item,index,arry){
console.log(item,index)
})
// 1 0
// 7 1
// 5 2
// 7 3
// 1 4
// 3 5

归并方法
归并方法包含reduce()和reduceRight()两个方法,这两个方法都会迭代数组中的所有项,然后生成一个最终返回值。
他们都接收两个参数,

  • 第一个参数是每一项调用的函数,函数接受是个参数分别是
    • 初始值
    • 当前值
    • 索引值
    • 当前数组
      函数需要返回一个值,这个值会在下一次迭代中作为初始值。
  • 第二个参数是迭代初始值,参数可选,如果缺省,初始值为数组第一项,从数组第一个项开始叠加,缺省参数要比正常传值少一次运算。

reduce()
该方法从数组的第一项开始,逐个遍历到最后一项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var dataArray = [1, 7, 5, 7, 1, 3];
var sum = dataArray.reduce(function(prev,cur,index,array) {
console.log(prev,cur,index);
return prev+cur;
})

console.log(sum);

// 1 7 1
// 8 5 2
// 13 7 3
// 20 1 4
// 21 3 5
// 24

设置了第二个参数,会多执行一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var dataArray = [1, 7, 5, 7, 1, 3];
var sum = dataArray.reduce(function(prev,cur,index,array) {
console.log(prev,cur,index);
return prev+cur;
},2)

console.log(sum);

//2 1 0
//3 7 1
//10 5 2
//15 7 3
//22 1 4
//23 3 5
//26

reduceRight()就是从右到左,就不详细说了。

最后更新: 2019年02月26日 20:23

原始链接: http://linjiad.github.io/2019/02/19/ES6/

× 请我吃糖~
打赏二维码