前言:
最近發布了es2017(即ES8),然后我也趁熱學習一下ES8
1、為什么要引入Object.entries方法
由于ES5,ES6,ES7并沒有提供遍歷對象的鍵-值對屬性的接口,所以可能官方腦袋一熱,為什么提供了獲取對象鍵集合的方法,也提供了獲取對象值集合的方法,為什么我們不提供獲取對象鍵值對的方法呢?
2、Object.entries方法定義
Object.entries(value : any) : Array<[string,any]>
,Object.entries方法接受一個參數,該參數的類型可以是任意的數據類型,Object.entries方法有返回值,返回值是一個數組,數組的元素的格式是[string,any],說明數組元素是一個只有2個元素的子數組,子數組的string對應對象的鍵,標準對象的鍵都是字符串類型的,所以這里子數組的第一個元素定義為string也是遵循了對象的標準規范,標準對象的鍵對應的值可以是任何類型的,所以子數組的第二個元素的類型也可以是任意數據類型,其實你可以理解為返回值是一個二維數組
3、Object.entries如何使用
const kv=Object.entries(obj1);
console.log(kv); //[["name","luochao"],["age",22]]
同樣適用于數組和字符串
const obj=Object.entries('lc');
console.log(obj)//[["0","l"],["1","c"]]
const arr=Object.entries([1,2]);
console.dir(arr);//[["0","1"],["1","2"]]
傳入的對象的鍵是數值類型時,它會將返回按鍵排序之后的數據
const s1={
3 : 'lc',
1 : 'yx',
"luochao": "22"
}
console.log(Object.entries(s1)) //[["1","yx"],["3","lc"],["luochao","22"]]
那么猜想它當對象的減值是字符串類型時,它返回的數據是否會根據鍵的ASCII碼值進行排序呢
const s1={
c : 'lc',
b : 'yx',
a : "22"
}
console.log(Object.entries(s1)) //[["c","lc"],["b","yx"],["a","22"]]
很遺憾,它返回的數據沒有根據鍵的ASCII碼值進行排序
4、Object.entries并不待見對象的任意屬性
Object.entries要求傳入對象的屬性必須是可被枚舉的,可被枚舉是指對象屬性的屬性裝飾符enumerable被設置為true,使用Object構造函數創建的對象,默認屬性的屬性裝飾符enumerable都是true
let luochao = Object.create(
{},
{ getAge : {value:function () { return this.age }} }
);
luochao.age = 22;
console.log(Object.keys(luochao)) //[["age",22]]
使用Object.create創建的對象必須顯式的給對象的屬性添加屬性裝飾符enumerable:true,該屬性才是可以被枚舉的
let luochao = Object.create(
{},
{ getAge : {value:function () { return this.age },enumerable:true} }
);
luochao.age = 22;
console.log(Object.entries(luochao)) //[["getAge",function () { return this.age }],["age",22]]
對象的屬性是Symbol類型時,該屬性也是不可以被枚舉的,即該屬性無法被Object.entries遍歷,注意Symbol類型用作對象的屬性時必須帶中括號[],不然就會被對象當做普通的字符串處理
const lc=Symbol('luochao');
const obj1={
[lc]: 'lc',
age: 22
}
const kv=Object.entries(obj1);
console.log(kv);//[["age",22]]
5、如何更方便的拿到Object.entries返回數據的每一個鍵值對
既然Object.entries返回的是二維數組,那么數組是原生就有部署遍歷接口的,那我們只需要對二維數組進行for of遍歷便可以拿到每一個數組元素,然后對子數組進行解構賦值便可以拿到鍵和值
let obj2 = { lc: 22, yx: 21 };
for (let [k,v] of Object.entries(obj2)) {
console.log(k,v);
//lc 22
//yx 21
}
6、Object.entries的返回值可以用作哪個原生數據解構的參數
由于Object.entries返回的是二維數組,而使用Map的構造函數實例化map對象傳入的參數就是二維數組,所以Object.entries的返回值就可以用作Map構造函數的參數
let map = new Map(Object.entries({
"name": "luochao",
"age": 22,
}));
console.log(map) //Map {"name" => "luochao", "age" => 22}
console.log(JSON.stringify([...map])); //[["name","luochao"],["age",22]]
//由于map是一個二維數組,自然可以使用擴展運算符將二維數組的元素都拆分出來
既然說到map結構,那我就來說一說我的理解,map結構我覺得就是為了解決對象的鍵只能是單一的字符串提出來的,仔細看看Map結構會發現和對象相比的差異就是:冒號被他替換成了箭頭符號,然后“對象”前面多了個Map標識,通過Map內置的方法,你可以達到和操作對象一樣的體驗,下面我們看看Map原型上面掛載的方法
我們看到Map.prototype上面部署了[Symbol.iterator]方法,是不是想到了什么,沒錯,Map結構部署了遍歷界口,它可以被for of遍歷
let map = new Map(Object.entries({
"name": "luochao",
"age": 22,
}));
for(const kv of map){
console.log(kv) //["name","luochao"],["age","22"]
}
map的方法我就不全部去演示怎么使用了,我想你們應該是都懂的,不懂就多試試啦,實踐是檢驗事實的標準,我只想說由于Map結構的鍵可以是對象,對象是引用類型,引用類型必須要指向同一塊內存地址才是相等的,否則是不相等的,例如下面的情況
let map = new Map([[{"like":"jianshen"},1],["name","luochao"]]);
console.log(map.get({"like":"jianshen"})); //undefined
map通過get方法獲取鍵{"like":"jianshen"}時,相當于新創建了一個{"like":"jianshen"}對象,所以這兩個看似一樣的對象其實不是一個對象,所以會出現undefined,你像下面這段代碼這么處理就是正確的,這是因為obj指針始終指向的是內存中的同一塊內存地址,所以能夠取到{"like":"jianshen"}鍵對應的值1
const obj={"like":"jianshen"}
let map = new Map([[obj,1],["name","luochao"]]);
console.log(map.get(obj)); //1