Array
Array.from()
Array.from()方法從一個(gè)類似數(shù)組或可迭代對象創(chuàng)建一個(gè)新的,淺拷貝的數(shù)組實(shí)例。
//將Set結(jié)構(gòu)的數(shù)據(jù)轉(zhuǎn)換為真正的數(shù)組
console.log(Array.from(new Set([1,5,2,8,8,4])))//[1,5,2,8,4]
//將字符串轉(zhuǎn)換為數(shù)組
console.log(Array.from('foo'))//["f", "o", "o"]
//接受第二個(gè)參數(shù),作用類似于數(shù)組的map方法
console.log(Array.from([1, 2, 3], x => x + x))//[2, 4, 6]
Array.prototype.flat()
Array.flat()方法會(huì)按照一個(gè)可指定的深度遞歸遍歷數(shù)組,并將所有元素與遍歷到的子數(shù)組中的元素合并為一個(gè)新數(shù)組返回。換句話說,就是將嵌套的數(shù)組“拉平”(默認(rèn)只會(huì)“拉平”一層),變成一維數(shù)組。該方法返回一個(gè)新數(shù)組,對原數(shù)據(jù)沒有影響
var newArray = arr.flat([depth])
depth指定要提取嵌套數(shù)組的結(jié)構(gòu)深度,默認(rèn)值為 1。
//默認(rèn)depth為 1
const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat());//[0, 1, 2, 3, 4]
//depth為 2
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2));//[0, 1, 2, [3, 4]]
//使用 Infinity,可展開任意深度的嵌套數(shù)組
var arr3 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
console.log(arr3.flat(Infinity));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
//flat() 方法會(huì)移除數(shù)組中的空項(xiàng)
var arr4 = [1, 2, , 4, 5];
console.log(arr4.flat());//[1, 2, 4, 5]
補(bǔ)充:flatMap()方法對原數(shù)組的每個(gè)成員執(zhí)行一個(gè)函數(shù),相當(dāng)于執(zhí)行Array.prototype.map(),然后對返回值組成的數(shù)組執(zhí)行flat()方法。該方法返回一個(gè)新數(shù)組,不改變原數(shù)組。
// 只能展開一層數(shù)組。相當(dāng)于 [[2, 4], [3, 6], [4, 8]].flat()
console.log([2, 3, 4].flatMap((x) => [x, x * 2]));// [2, 4, 3, 6, 4, 8]
將二維數(shù)組轉(zhuǎn)化為一維的其他方法
//reduce方法
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]
//將多維數(shù)組轉(zhuǎn)化為一維
let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = function(arr){
return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
Array.prototype.sort()
Array.sort()對數(shù)組的元素進(jìn)行排序,并返回?cái)?shù)組。默認(rèn)排序順序是在將元素轉(zhuǎn)換為字符串,然后比較它們的UTF-16代碼單元值序列時(shí)構(gòu)建的
console.log(['March', 'Jan', 'Feb', 'Dec'].sort());//["Dec", "Feb", "Jan", "March"]
console.log([1, 3, 1000,'a', 'Dec','A'].sort());//[1, 1000, 3, "A", "Dec", "a"]
//一個(gè)數(shù)組按照另一個(gè)數(shù)組排序
let arr = [{id:5},{id:8},{id:4},{id:1},{id:6}]
let arr2 = [1,2,3,4,5,6,7,8]
let arr3 = arr.sort((a,b)=>{
return arr2.indexOf(a.id) - arr2.indexOf(b.id)
})
console.log(arr3)// [{id: 1}, {id: 4}, {id: 5}, {id: 6}, {id: 8}]
Array.prototype.filter()
filter() 方法創(chuàng)建一個(gè)新數(shù)組, 其包含通過所提供函數(shù)實(shí)現(xiàn)的測試的所有元素。 filter把傳入的函數(shù)依次作用于每個(gè)元素,然后根據(jù)返回值是 true 還是false決定保留還是丟棄該元素
//去重
let arr = [1,4,6,3,6,8,9,1];
let newarr = arr.filter((item,index,array) => {
return array.indexOf(item) === index
})
console.log(newarr);// [1,4,6,3,8,9]
//篩選出不同元素
let arr = [{id:5},{id:8},{id:4},{id:1},{id:6}]
let arr2 = [{id:1},{id:2},{id:3},{id:4},{id:5}]
let arr3 = arr.filter(x=> arr2.every(y=>x.id !== y.id))
console.log(arr3)//[{id: 8},{id: 6}]
去重其他方法
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
if(!pre.includes(cur)){
return pre.concat(cur)
}else{
return pre
}
},[])
console.log(newArr);// [1, 2, 3, 4]
//利用set
console.log([...new Set(arr)])//[1,2,3,4]
Array.prototype.every()
every() 方法測試一個(gè)數(shù)組內(nèi)的所有元素是否都能通過某個(gè)指定函數(shù)的測試。它返回一個(gè)布爾值。
let arr = ['apple','banana','orange','pear','watermelon'];
let every = arr.every((item,index,array) => {
return item.length>10
})
console.log(every);//false
Array.prototype.some()
some() 方法與every() 方法相反,some() 方法測試數(shù)組中是不是至少有1個(gè)元素通過了被提供的函數(shù)測試。它返回的是一個(gè)Boolean類型的值。
let arr = [1,2,3,4,5];
let someResult = arr.some((item,index,arr) => item%2==0);
console.log(someResult); //true
Array.prototype.forEach()和Array.prototype.map()
forEach()方法對數(shù)組的每個(gè)元素執(zhí)行一次給定的函數(shù)。
map()方法創(chuàng)建一個(gè)新數(shù)組,其結(jié)果是該數(shù)組中的每個(gè)元素是調(diào)用一次提供的函數(shù)后的返回值。
區(qū)別:forEach()方法不會(huì)返回執(zhí)行結(jié)果,而是undefined。也就是說,forEach()會(huì)修改原來的數(shù)組。而map()方法會(huì)得到一個(gè)新的數(shù)組并返回。
//forEach
let arr = [1,2,3,4,5];
arr.forEach((item,index,array) => {
arr[index] = item + 1;
})
console.log(arr)//[ 2, 3, 4, 5, 6 ]
//map
let arr = [1,2,3,4,5];
let arr2 = arr.map((item,index,arr) => item*2)
console.log(arr2)//[ 2, 3, 4, 5, 6 ]
Array.prototype.reduce()
reduce() 方法對數(shù)組中的每個(gè)元素執(zhí)行一個(gè)由您提供的reducer函數(shù)(升序執(zhí)行),將其結(jié)果匯總為單個(gè)返回值。
第一個(gè)參數(shù)callback函數(shù): pre為上次return的值,next為數(shù)組的本次遍歷的項(xiàng)
第二個(gè)參數(shù)為初始值,也是第一個(gè)pre
let arr = [1,2,3,4,5];
let sum = arr.reduce((pre,next) => {
console.log(pre,next)//0,1 1,2 3,3 6,4 10,5
return pre + next
},0)
console.log(sum) //15
//若initialValue 為 1
let sum = arr.reduce((pre,next) => {
console.log(pre,next)//1,1 2,2 4,3 7,4 11,5
return pre + next
},1)
console.log(sum) //16
//引申 pipe
const pipe = ...args => x =>
args.reduce(
(outputValue, currentFunction) => currentFunction(outputValue),
x
)
//示例
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
const f1 = x => {
return x+1;
}
const f2 = x => {
return 2 * x;
}
// (1+1)*2 = 4
let result = pipe(f1, f2)(1);
console.log(result);
Array.prototype.includes()
includes() 方法用來判斷一個(gè)數(shù)組是否包含一個(gè)指定的值,根據(jù)情況,如果包含則返回 true,否則返回 false。
const pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));// true
跟indexOf很像,但還是有區(qū)別的
const arr = [1,2,3,4,5,NaN]
console.log(arr.includes(NaN))//true
console.log(arr.indexOf(NaN))//-1
ES6數(shù)組:兩個(gè)數(shù)組或數(shù)組對象取并集、交集、差集
http://m.itdecent.cn/p/20523688cbee
Object
Object .entries(),Object .keys()和Object .values()
都返回一個(gè)由一個(gè)給定對象的自身可枚舉屬性的數(shù)組。唯一的區(qū)別是keys()是對鍵名的遍歷、values()是對鍵值的遍歷,entries()是對鍵值對的遍歷。
補(bǔ)充: Object.fromEntries() 方法把鍵值對列表轉(zhuǎn)換為一個(gè)對象。
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
console.log(Object.keys(obj))// ['foo', 'bar']
console.log(Object. values(obj))// ['baz', 42]
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
const obj = Object.fromEntries(entries);
console.log(obj);// expected output: Object { foo: "bar", baz: 42 }
// iterate through key-value gracefully
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}
// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
//將Object轉(zhuǎn)化為Map
var obj = { foo: "bar", baz: 42 };
var map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }
Object.entries("foo");//[["0", "f"],["1", "o"],["2", "o"]]
//在ES5里,如果此方法的參數(shù)不是對象(而是一個(gè)原始值),那么它會(huì)拋出 TypeError。在ES2015(ES6)中,非對象的參數(shù)將被強(qiáng)制轉(zhuǎn)換為一個(gè)對象
Object.keys("foo");// TypeError: "foo" is not an object (ES5 code)
Object.keys("foo");// ["0", "1", "2"] (ES2015 code)
console.log(Object.values('foo')); // ['f', 'o', 'o']
其他
for..of..和for...in...
for in :以任意順序遍歷一個(gè)對象的除Symbol以外的可枚舉屬性。為遍歷對象屬性而構(gòu)建的,不建議與數(shù)組一起使用,數(shù)組可以用。
for of :在可迭代對象包括Array,Map,Set,String,TypedArray,arguments 對象等等上創(chuàng)建一個(gè)迭代循環(huán)。
const obj = {name: 'amy', age: 18, gender: 'man'}
const arr = [1,2,3,4,5]
for (let key in obj){
console.log(key)//name age gender
}
for (let index in arr){
console.log(index)//0 1 2 3 4
}
for (let item of arr){
console.log(item)//1 2 3 4 5
}
async/await
以同步方式執(zhí)行異步操作。
場景:接口一,請求到數(shù)據(jù)一,而數(shù)據(jù)一被當(dāng)做請求二的參數(shù)去請求數(shù)據(jù)二。用promise會(huì)嵌套多層,美觀及可讀性較差,可以用async/await,但要注意以下幾點(diǎn):
-await只能在async函數(shù)里使用
-await后面最好接Promise,如果后面接的是普通函數(shù)則會(huì)直接執(zhí)行
-async函數(shù)返回的是一個(gè)Promise
function fn1(){
return new Promise((resolve,reject) => {
setTimeout(()=>{
resolve('fn1success')
},1000)
})
}
function fn2(data){
return new Promise((resolve,reject) => {
setTimeout(()=>{
resolve('fn2success,'+data)
},2000)
})
}
async function req() {
const data1 = await fn1()//等待1s后返回?cái)?shù)據(jù)再往下執(zhí)行
const data2 = await fn2(data1)//拿fn1的返回值去請求fn2,2s后返回?cái)?shù)據(jù)
console.log(data2)//共3s后輸出 fn2success,fn1success
}
req()
String.trimStart && String.trimEnd
trim方法,可以清除字符串首尾的空格,trimStart和trimEnd用來單獨(dú)去除字符串的首和尾的空格
const str = ' 哈哈哈 '
console.log(str.trim())//哈哈哈
console.log(str.trimStart())//哈哈哈
console.log(str.trimEnd())// 哈哈哈
?. 和 ?? (ES11)
?.為可選鏈
//比如我們需要一個(gè)變量,是數(shù)組且有長度,才做某些操作
const list = null
// do something
if (list && list.length) {
// do something
}
// 使用可選鏈
const list = null
// do something
if (list?.length) {
// do something
}
//比如有一個(gè)對象,我要取一個(gè)可能不存在的值,甚至我們都不確定obj是否存在
const obj = {
cat: {
name: '哈哈'
}
}
const dog = obj && obj.dog && obj.dog.name // undefined
// 可選鏈
const obj = {
cat: {
name: '哈哈'
}
}
const dog = obj?.dog?.name // undefined
//數(shù)組取索引為1的值
const item = arr?.[1]
??為空位合并運(yùn)算符
使用||運(yùn)算符,只要左邊是假值,就會(huì)返回右邊的數(shù)據(jù)
const str = '哈哈哈'
console.log('' || str)//哈哈哈
console.log(0 || str)//哈哈哈
console.log(null || str)//哈哈哈
console.log(undefined || str)//哈哈哈
console.log(false || str)//哈哈哈
而??和||最大的區(qū)別是,在??這,只有undefined和null才算假值
console.log('' ?? str)//''
console.log(0 ?? str)//0
console.log(null ?? str)//哈哈哈
console.log(undefined ?? str)//哈哈哈
console.log(false ?? str)//false
數(shù)組和對象相互轉(zhuǎn)換
export const arrToObj = (arr) =>{
return arr.reduce((prev,current)=>{
if (current._id){
prev[current._id] = current
}
return prev
},{})
}
export const objToArr =(obj) =>{
return Object.keys(obj).map(key=>obj[key])
}
擴(kuò)展 用ts定義
interface TestProps {
_id: string;
name: string;
}
const testData: TestProps[] = [{ _id: '1', name: 'a' }, { _id: '2', name: 'b' }]
const testData2:{[key:string]:TestProps} ={
1:{_id: '1', name: 'a'},
2:{ _id: '2', name: 'b' }
}
export const arrToObj = <T extends {_id?:string}>(arr:Array<T>) =>{
return arr.reduce((prev,current)=>{
if (current._id){
prev[current._id] = current
}
return prev
},{} as {[key:string]:T})
}
export const objToArr = <T>(obj:{[key:string]:T}) =>{
return Object.keys(obj).map(key=>obj[key])
}