本系列博客为 ES6 基础语法的使用及总结,如有错误,欢迎指正。
重学 ES6 之出来混迟早要还的(四)主要包括Array.from()、Array.of()、find()/findIndex()、some()/every()、Promise。
Array.from()/Array.of()
这两个方法不是原型上面的方法,直接使用会报错
let arr = [1,2,3];
console.log(arr.from());
//Uncaught TypeError: arr.from is not a function
console.log(arr.of());
//Uncaught TypeError: arr.of is not a function
Array.from()
1. 用法
用于把一个类数组对象或者是一个可遍历对象转换为一个真正的数组
类数组对象是啥?
具有索引属性 (数字),有 length 属性的对象;比如 NodeList 对象
可遍历对象是啥?
别问,问就是让你去看前面两篇笔记
(1) 格式:Array.from(arrayLike[, mapFn[, thisArg]])
(2) 参数:
- arrayLike 想要转换成数组的伪数组对象或可迭代对象。
- mapFn 可选 如果指定了该参数,新数组中的每个元素会执行该回调函数。
- thisArg 可选 执行回调函数 mapFn 时 this 对象。
(3) 返回值:一个新的数组实例。
(4) 示例
// 从 String 生成数组
Array.from('foo');
// ["f", "o", "o"]
console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]
Array.from(obj, mapFn, thisArg)
的格式相当于 Array.from(obj).map(mapFn, thisArg)
let oLis = document.querySelectorAll('li');
let num = Array.from(oLis).map(li => li.innerHTML);
console.log(num); //["1", "2", "3"]
// 等价于
let liArr = Array.from(oLis,li => li.innerHTML);
console.log(liArr); //["1", "2", "3"]
2. 应用场景
-
可以将函数里面的 arguments 对象转换为数组,多嘴一句:在这篇里面也说了剩余参数也可以将函数参数打包为一个数组。
function list(...numbers) {console.log(numbers); } list(1,2,3,4,5); function list2() {console.log(Array.from(arguments)); } list2(6,7,8,9,10);
-
将字符串转为字符串数组
let arr = Array.from('ridiculous'); console.log(arr); //["r", "i", "d", "i", "c", "u", "l", "o", "u", "s"] let str = 'ridiculous'; let arr2 = str.split(''); console.log(arr2); //["r", "i", "d", "i", "c", "u", "l", "o", "u", "s"]
Array.of()
1. 用法 Array.of()
方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of()
和 Array
构造函数之间的区别在于处理整数参数:Array.of(7)
创建一个具有单个元素为 7 的数组 ( 注意:数组的长度是 1),Array(7)
创建一个长度为 7 的空数组(注意:这是指一个有 7 个空位 (empty) 的数组,而不是由 7 个 undefined
组成的数组)。
let arr = Array(5);
console.log(arr); //[empty × 5] 是一个长度为 5,数值都为空的数组
let arr2 = Array.of(5);
console.log(arr2); //[5] 是一个长度为 1,元素值为 5 的数组
let arr = Array(0);
console.log(arr); //[]
let arr2 = Array.of(0);
console.log(arr2); //[0]
也就是说使用 Array.of()
能够保证传入的数据和返回结果的一致性,不管传入多少个参数,返回的是由这些元素组成的数组;弥补了 Array()
构造函数的不足
let arr = Array(1,2,3);
console.log(arr); //[1,2,3]
let arr2 = Array.of(1,2,3);
console.log(arr2); //[1,2,3]
find()/findIndex()/some()/every()
find()
find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
找到满足条件的第一个就会立即停止
1. 用法
格式:arr.find(callback[, thisArg])
参数:① callback 在数组每一项上执行的函数,接收 3 个参数:
- element 当前遍历到的元素。
- index 可选 当前遍历到的索引。
- array 可选 数组本身。
② thisArg 可选 执行回调时用作 this 的对象。
返回值:数组中第一个满足所提供测试函数的元素的值,都找不到否则返回 undefined。
let inventory = [{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
let cherry = inventory.find(fruit => fruit.name === 'cherries');
console.log(cherry); // {name: 'cherries', quantity: 5}
findIndex()
findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。找不到则返回 -1。
1. 用法
格式:arr.findIndex(callback[, thisArg])
参数:① callback 针对数组中的每个元素, 都会执行该回调函数, 执行时会自动传入下面三个参数:
- element 当前元素。
- index 当前元素的索引。
- array 调用 findIndex 的数组。
② thisArg 可选。执行 callback 时作为 this 对象的值.
返回值:数组中通过提供测试函数的第一个元素的索引。否则,返回 -1
let cherryIndex = inventory.findIndex(fruit => fruit.name === 'cherries');
console.log(cherryIndex); //2
some()
some() 方法测试数组中是不是至少有 1 个元素通过了被提供的函数测试。它返回的是一个 Boolean 类型的值。
找到满足条件的第一个就会立即停止
1. 用法
格式:arr.some(callback(element[, index[, array]])[, thisArg])
参数:① callback 用来测试每个元素的函数,接受三个参数:
- element 数组中正在处理的元素。
- index 可选 数组中正在处理的元素的索引值。
- array 可选 some()被调用的数组。
② thisArg 可选
执行 callback 时使用的 this 值。
返回值:数组中有至少一个元素通过回调函数的测试就会返回 true;所有元素都没有通过回调函数的测试返回值才会为 false。
let isZero = inventory.some(fruit => fruit.quantity === 0);
console.log(isZero); //true
every()
every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
如果有一个为 false,则立即返回 false,后面的不再执行
1. 用法
格式:arr.every(callback[, thisArg])
参数:① callback 用来测试每个元素的函数,它可以接收三个参数:
- element 用于测试的当前值。
- index 可选 用于测试的当前值的索引。
- array 可选 调用 every 的当前数组。
② thisArg 执行 callback 时使用的 this
值。
返回值:如果回调函数的每一次返回都为 truthy 值,返回 true,否则返回 false。
let allZero = inventory.every(fruits => fruits.quantity === 0);
console.log(allZero); //false
Promise
官方说法之又臭又长不看版:
Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.
Promise 构造函数执行时立即调用
executor
函数,resolve
和reject
两个函数作为参数传递给executor
(executor 函数在 Promise 构造函数返回所建 promise 实例对象前被调用)。resolve
和reject
函数被调用时,分别将 promise 的状态改为 fulfilled(完成)或 rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功 / 失败),要么调用 resolve 函数来将 promise 状态改成 fulfilled,要么调用reject
函数将 promise 的状态改为 rejected。如果在 executor 函数中抛出一个错误,那么该 promise 状态为 rejected。executor 函数的返回值被忽略。
1.Promise 基本概念
1.1 what
promise 是 ES6 中新增的异步编程解决方案。简单说就是一个容器,里面保存着某个未来才会结束的事件的结果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。可以通过 new Promise(function(resolve, reject)
来创建
1.2 why
通过 Promise 就可以实现:用同步的流程来表示异步的操作;解决回调顺序的不确定性,解决回调地狱的问题
1.3 how
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve
和reject
。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve
函数的作用是,将 Promise 对象的状态从“未完成”变为“成功”(即从 Pending
变为Resolved
),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject
函数的作用是,将 Promise 对象的状态从“未完成”变为“失败”(即从 Pending
变为Rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
let p = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){resolve(value);
} else {reject(error);
}
});
2.Promise 对象三种状态(面试必问)
- pending:默认状态,只要没有说明 promise 任务是成功还是失败就是 pending 状态
- fulfilled(resolved):只要调用 resolve 函数, 状态就会变为 fulfilled, 表示操作成功
- rejected:只要调用 rejected 函数, 状态就会变为 rejected, 表示操作失败
3.Promise 常用的方法有哪些?它们的作用是什么?
3.1 Promise.then
- Promise 实例具有 then 方法,也就是说,then 方法是定义在原型对象 Promise.prototype 上的。
- 它的作用是为 Promise 实例添加状态改变时的回调函数。
- then 方法的第一个参数是 resolved 状态的回调函数,第二个参数(可选)是 rejected 状态的回调函数。
3.2 Promise.catch
Promise.catch 方法是 .then(null, rejection)
或.then(undefined, rejection)
的语法糖,用于指定发生错误时的回调函数。
3.3 Promise.all
all 方法接收一个数组,,当所有实例 promise 的结果都是成功时,才会执行后面 then 方法里面的内容
如果有一个 promise 实例的状态是失败的,那么就会执行 catch 方法
const userPromise = new Promise((resolve,reject) =>{setTimeout(() => {resolve(['lucy','lily','eli']);
},2000)
});
const moviePromise = new Promise((resolve,reject) => {setTimeout(() => {// resolve({name: '卡萨布兰卡',score: '9.8', published: '1964'});
reject('no movie found');
},500);
});
Promise.all([userPromise,moviePromise])
.then(response => {console.log(response);
let [user,movie] = response;
console.log(user);
console.log(movie);
})
.catch(err => console.log(err));
已知 userPromise
的状态已经确定了是成功的,所以 all 方法返回的内容取决于 moviePromise
的状态:
如果 moviePromise
的状态是成功,则 all 方法执行 then 里面的内容。正常打印 response、user、movie
如果 moviePromise
的状态是失败,则 all 方法执行 catch 里面的内容。抛出错误
3.4 Promise.race
race 方法由数组里面第一个 promise 实例返回的状态决定,如果第一个 promise 返回的状态是成功,那么 race 方法执行 then 方法里面的内容;
如果第一个 promise 实例返回的状态是失败,则 race 方法执行 catch 方法里面的内容
const userPromise = new Promise((resolve,reject) =>{setTimeout(() => {resolve(['lucy','lily','eli']);
},2000)
});
const moviePromise = new Promise((resolve,reject) => {setTimeout(() => {resolve({name: '卡萨布兰卡',score: '9.8', published: '1964'});
// reject(Error('no movie found'));
},500);
});
Promise.race([userPromise,moviePromise])
.then(response => {console.log(response);
})
.catch(err => console.log(err));
race 方法执行的结果取决于先执行的 moviePromise
返回的结果,
如果 moviePromise
的状态是成功的,那么 race 方法执行 then 里面的内容。正常打印 response
如果 moviePromise
的状态是失败的,那么 race 方法执行执行 catch 里面的内容。抛出错误
4.Promise 常见面试题
let promise = new Promise((resolve, reject)=>{console.log('我是 promise 任务');
resolve('resolved')
})
promise.then(res =>{console.log(res)
})
console.log("我是同步任务");
setTimeout(()=>{console.log("我是延时任务");
}, 0)
答案:执行顺序:我是 promise 任务、我是同步任务、resolved、我是延时任务。