Js基礎知識7-Es6新增對象Map和set數據結構

前言

JavaScript中對象的本質是鍵值對的集合,ES5中的數據結構,主要是用Array和Object,可是鍵只能是字符串。爲了彌補這種缺憾,ES6帶來了一種新的數據結構Map。數組

Map也是鍵值對的集合,只是鍵不只能夠是字符串還能夠是其餘數據類型,好比:對象(是否是很神奇)。請看下面例子。。下面話很少說了,來一塊兒看看詳細的介紹吧。數據結構

Map 對象

Map結構提供了「值—值」的對應,任何值(對象或者原始值) 均可以做爲一個鍵或一個值,是一種更完善的Hash結構實現。若是你須要「鍵值對」的數據結構,Map比Object更合適。它相似於對象,也是鍵值對的集合,可是「鍵」的範圍不限於字符串,各類類型的值(包括對象)均可以看成鍵。函數

屬性

Map屬性this

  • Map.length 屬性length的值爲0。spa

  • Map.prototype 表示Map構造器的原型。容許添加屬性從而應用與全部的Map對象.net

Map實例 - 全部Map對象的實例都會繼承Map.prototype。prototype

  • Map.prototype.constructor 返回建立給map實例的構造函數,默認是Map函數。code

  • Map.prototype.size 返回Map對象的鍵值對的數量。對象

    var map = new Map([['one',1], ['two', 2], ['three', 3]]);
    console.log(map.constructor); //function Map() { [native code] }
    console.log(map.size); //3

方法

    //Iterator對象:可使用for..of進行迭代的對象
    var map = new Map([[1, 'one'],[2, 'two'], [3, 'three']]);

1.Map.prototype.set(key, value) 設置Map對象中鍵的值,返回該Map對象。blog

console.log(map.has(4));    //false
    map.set(4, 'four');
    console.log(map.has(4))    //true

2.Map.prototype.get(key) 返回鍵對應的值,若是不存在,則返回undefined。

map.get(1); //'one'

3.Map.prototype.has(key) 返回一個布爾值,表示Map實例是否包含鍵對應的值。

map.has(1); // true
    map.has(5); //false

4.Map.prototype.delete(key) 移除任何與鍵相關聯的值,而且返回該值,該值在以前會被Map.prototype.has(key)返回爲true。以後再調用則返回false。

console.log(map.has(1));    //true
    map.delete(1);
    console.log(map.has(1));    //false

5.Map.prototype.clear() 移除Map對象的全部鍵值對。

console.log(map.size);    //3
    map.clear();
    console.log(map.size);    //0

6.Map.prototype.entries() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每一個元素的[key, value]數組。

console.log(map);    //Map {1 => "one", 2 => "two", 3 => "three"}
    map.entries();
    console.log(map);    //Map {1 => "one", 2 => "two", 3 => "three"}

7.Map.prototype.forEach(callbackFn[, thisArg]) 按插入順序,爲Map對象裏的每一鍵值對調用一次callbackFn函數。若是爲forEach提供了thisArg,他將在每次回調函數中做爲this值。

map.forEach(function(value, key, mapObj) {
        console.log(value + '---' + key + '---' + mapObj);
        //value - Map對象裏每個鍵值對的值
        //key - Map對象裏每個鍵值對的鍵
        //mapObj - Map對象自己
        console.log(this); //this === window
    });

    map.forEach(function(value, key, mapObj) {
        console.log(value + '---' + key + '---' + mapObj);
        console.log(this);    //this === map
    }, map)

8.Map.prototype.keys() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每一個元素的鍵。

map.keys();    //MapIterator {1, 2, 3}

9.Map.prototype.values() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每一個元素的值。

map.values(); //

使用for..of方法迭代映射

var map = new Map();
    map.set(1, 'one');
    map.set(2, 'two');
    for (var [key, value] of map) {
        console.log(key + '---' + value);
    }
    // 1 --- one 2 --- two
    
    for (var key of map.keys()) {
        console.log(key);
    }
    // 1 2
    
    for (var value of map.values()) {
        console.log(value);
    }
    // 'one' 'two'

 常規用法綜合

var map = new Map();  //建立map對象
map.set('one', 1);
map.set('two', 2);
map.set('three', 3); 
//或者   var map = new Map([['one',1], ['two', 2], ['three', 3]]);

m.set(ul,'content'); //爲Map增長成員
m.get(ul);//獲取鍵 ul對應的值
m.has(ul);//返回布爾值,判斷是否含有鍵 ul
m.delete(ul);//刪除鍵 ul,成功返回true,失敗返回false
m.size //返回m長度
m.clear(); //清除m全部成員

Map VS Object

  • 一個對象一般都有本身的原型,因此一個對象總有一個"prototype"鍵。不過,從ES5開始可使用map = Object.create(null)來建立一個沒有原型的對象。

  • 一個對象的鍵只能是字符串或者Symbols,但一個Map的鍵能夠是任意值。

  • 你能夠經過size屬性很容易地獲得一個Map的鍵值對個數,而對象的鍵值對個數只能手動確認。

數據類型轉換

   ...擴展語句

擴展語法容許一個表達式在指望多個參數(用於函數調用)或多個元素(用於數組字面量)或多個變量(用於解構賦值)的位置擴展。

let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; 
console.log(arr1) // [3, 4, 5, 0, 1, 2]

   Map轉數據的最簡單方式是使用 ... 擴展運算符。例如:

var map = new Map([['one',1], ['two', 2], ['three', 3]]);
console.log(...map);  //["one", 1]   ["two", 2]   ["three", 3]

Map轉對象時,必須全部鍵都是字符串,使用Object.create()函數。Map轉JSON時,要求也要求全部鍵都是字符串,使用JSON.Stringify()函數。

須要注意的

       一、轉換時注意

       二、當鍵是對象時,必須是引用相同,才認爲鍵是相同的。只有對同一個對象的引用,Map結構纔將其視爲同一個鍵。這一點要很是當心。

var map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
//上面代碼的set和get方法,表面是針對同一個鍵,但實際上這是兩個值,內存地址是不同的,所以get方法沒法讀取該鍵,返回undefined。

       三、若是Map的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map將其視爲一個鍵,包括0和-0。另外,雖然NaN不嚴格相等於自身,但Map將其視爲同一個鍵。

    var map = new Map();
    map.set(Number('aa111'), 'isNaN');
    map.set(Number('bb222'), 'also is NaN');
    map.get(NaN);    //'also is NaN'

       四、注意區分Map對象與JavaScript Array map() 方法 

Array map() 語法
array.map(function(currentValue,index,arr), thisValue)

實例1
//返回一個數組,數組中元素爲原始數組的平方根:
var numbers = [4, 9, 16, 25];
function myFunction() {
    x = document.getElementById("demo")
    x.innerHTML = numbers.map(Math.sqrt);
}
//2,3,4,5

實例2
//數值項求平方:
var data = [1, 2, 3, 4];
var arrayOfSquares = data.map(function (item) {
  return item * item;
});
alert(arrayOfSquares); // 1, 4, 9, 16

Set 對象

  簡要

ES6提供了新的數據結構Set。它相似於數組,可是成員的值都是惟一的,沒有重複的值。

Set函數能夠接受一個數組(或相似數組的對象)做爲參數,用來初始化。

Set對象容許你存儲任意類型的惟一值(不能重複),不管它是原始值或者是對象引用。

Set自己是一個構造函數,用來生成Set數據結構。

Set結構有如下屬性:

  • Set.prototype.constructor: 構造函數,默認就是Set函數。
  • set.prototype.size : 返回Set的成員總數。

Set結構有如下方法:

  • add(value) : 添加某個值,返回Set結構自己。
  • delete(value) : 刪除某個值,返回一個布爾值,表示是否成功。
  • has(value) : 返回一個布爾值,表示該值是否爲Set的成員。
  • clear() : 清除全部成員,沒有返回值。

Set遍歷操做:

  • keys():返回鍵名的遍歷器
  • values(): 返回健值對的遍歷器
  • entries():返回鍵值對的遍歷器
  • forEach(): 每一個成員

Set屬性

  • Set.length 屬性length的值爲0。

  • Set.prototype 表示Set構造器的原型。容許向全部Set對象添加新的屬性。

Set實例 

       全部Set對象的實例都會繼承Set.prototype。

  • Set.prototype.constructor 返回建立給set實例的構造函數,默認是Set函數。

  • Set.prototype.size 返回Set對象的鍵值對的數量。

var sset = new Set(['one', 'two', 'three']);
    console.log(sset.constructor); //function Set() { [native code] }
    console.log(sset.size); //3

Set方法

//建立Set實例
    //1.
    var sset = new Set();
    sset.add('one');
    sset.add('two');
    sset.add('three');  
    //2.
    var sset= new Set(['one', 'two', 'three']);

1.Set.prototype.add(value) 在Set對象尾部添加一個元素。返回該Set對象。

sset.add('four');
    console.log(sset);    //Set {"one", "two", "three", "four"}

2.Set.prototype.clear() 移除Set對象內的全部元素。

sset.clear();
    console.log(sset.size);    //0

3.Set.prototype.delete(value) 移除Set的中與這個值相等的元素,返回Set.prototype.has(value)在這個操做前會返回的值(即若是該元素存在,返回true,不然返回false)。Set.prototype.has(value)在此後會返回false。

console.log(sset.has('one'));    //true
    sset.delete('one');
    console.log(sset.has('one'));    //false

4.Set.prototype.entries() 返回一個新的迭代器對象,該對象包含Set對象中的按插入順序排列的全部元素的值的[value, value]數組。爲了使這個方法和Map對象保持類似, 每一個值的鍵和值相等。

5.Set.prototype.forEach(callbackFn[, thisArg]) 按照插入順序,爲Set對象中的每個值調用一次callBackFn。若是提供了thisArg參數,回調中的this會是這個參數。

sset.forEach(function(value, key, setObj) {
        console.log(value + '---' + key + '---' + setObj);
        //value - Set對象裏每個鍵值對的值
        //key - Set對象裏每個鍵值對的鍵 === 值
        //mapObj - Set對象自己
        console.log(this); //this === window
    });

    sset.forEach(function(value, key, setObj) {
        console.log(value + '---' + key + '---' + setObj);
        console.log(this);    //this === sset
    }, sset)

6.Set.prototype.has(value) 返回一個布爾值,表示Map實例是否包含鍵對應的值。

sset.has('one'); // true
    sset.has('fivr'); //false

7.Set.prototype.keys() 與values()方法相同,返回一個新的迭代器對象,該對象包含Set對象中的按插入順序排列的全部元素的值。

sset.keys();    //SetIterator {"one", "two", "three"}

8.Set.prototype.values() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每一個元素的值。

sset.values(); //SetIterator {"one", "two", "three"}

使用for..of方法迭代映射

var sset = new Set();
    sset.add(1);
    sset.add(2);
    for (var value of sset) {
        console.log(value);
    }
    // 1 2
    
    for (var key of sset.keys()) {
        console.log(key);
    }
    // 1 2
    
    for (var value of sset.values()) {
        console.log(value);
    }
    // 1 2

Set 與 Array 

var myArray = ["value1", "value2", "value3"];

// 用Set構造器將Array轉換爲Set
var mySet = new Set(myArray);

mySet.has("value1"); // returns true

// 用...(展開操做符)操做符將Set轉換爲Array
console.log([...mySet]); // 與myArray徹底一致

Array.from方法能夠將Set結構轉換爲數組。

var items = new Set([1, 2, 3, 4, 5]);
var array = Array.from( items );

這也提供了一種除去數組中重複元素的方法。

function dedupe( array ) {
    return Array.from( new Set(array) );
}

或者以下寫也能夠,比較簡單的數組去重

[...new Set([1,3,4,5,1,2,3,3,4,8,90,3,0,5,4,0])]

Set 注意

 一、var sset = new Set('one', 'two', 'three');  //這樣的錯誤的

 二、值的相等規則:NaN 是與NaN是相同的(雖然NaN !== NaN),除此以外全部的值都根據'==='判斷。

    var sset= new Set();
    sset.add(Number('aa111'));
    sset.add(Number('bb222'));
    sset.add('cc333'));
    //Set {NaN, "cc333"}

 三、向Set加入值的時候,不會發生類型轉換。這意味着,在Set中5和」5」是兩個不一樣的值。

 weakset對象

WeakSet結構與Set相似,也是不重複的值的集合。

WeakSet和Set的區別:

  • 1.WeakSet的成員只能是對象,而不能是其餘類型的值
  • 2.WeakSet中的對象都是弱引用,即垃圾回收機制不考慮WeakSet對該對象的引用,也就是說,若是其餘對象都再也不引用該對象,那麼垃圾回收機制會自動回收該對象所佔用的內存,不考慮該對象還存在於WeakSet之中。這個特色意味着,沒法引用WeakSet的成員,所以WeakSet是不可遍歷的。

WeakSet結構的三個方法adddeletehasWeakSet的一個用處是儲存DOM節點,而不用擔憂這些節點會從文檔中移除時,會引起內存泄露。

相關文章
相關標籤/搜索