[TOC]
>[success] # Set集合與Map集合
<br/>
~~~
'數組'一直是'JavaScript'中唯一的'集合類型',也就是'數組類型','JavaScript'的'數組'的功能與其他
語言一樣,但在'ES6標準'制定以前,由于可選的'集合類型'有限,'數組'使用的又是'數值型索引',因而經常
被創建'隊列'和'棧'。如果開發者們需要使用'非數值型索引',就會用到'非數組對象'的'數據結構',而這
就是'Set集合'和'Map集合'的早期實現。
~~~
<br/>
~~~
集合類型:
1. 'Array'
2. 'Set'
3. 'Map'
~~~
<br/>
>[success] ## Set集合
<br/>
~~~
'Set集合'是一種'無重復元素的列表',開發者們一般不會逐一(東北話:'挨個')'讀取數組中的元素',
也不太可能逐一(東北話:'挨個')'訪問Set集合中的每個元素',通常的做法是'檢測給定的值,在某集合中是否存在'
~~~
<br/>
>[success] ## Map集合
<br/>
~~~
'Map集合'內含多組'鍵值對',集合中每個元素分別存放著可訪問的'鍵名'和它對應的'值','Map集合'經常被用于
'緩存頻繁取用的數據'。
~~~
<br/>
>[success] ## ES5實現Set集合功能 / Map集合
<br/>
~~~
在'ES6'發布之前,開發者們在'ES5'中用'非數組對象'的方式實現了類似的功能。
~~~
<br/>
1. Set集合實現
~~~
// 創建一個空對象,沒有prototype屬性的對象
let set = Object.create(null);
// 創建一個set對象的屬性
set.foo = true;
if(set.foo){ // 檢查屬性是否存在
// 要執行的代碼
}
~~~
<br/>
2. Map集合實現
~~~
// 創建一個空對象,沒有prototype屬性的對象
let map = Object.create(null);
// 創建一個Map對象的屬性
map.foo = "bar";
// 獲取已存值
let value = map.foo;
console.log(value) // "bar"
~~~
<br/>
>[warning] ## ES5實現Set集合、Map集合的一些問題
<br/>
~~~
雖然能用'ES5'能實現出'Set集合'和'Map集合',但是非常的'局限性',如果對象的'屬性'有限制的話,
例如,'所有對象的屬性必須是字符串類型'、'每個鍵名(key)都是唯一的'。
~~~
<br/>
1. 用`number類型`值作為對象的屬性的問題
~~~
// 創建一個空對象
let map = Object.create(null)
// 用number類型值給對象創建屬性,并且賦值
map[5] = 'foo'
console.log(map[5]) // foo
// 等同
console.log(map['5']) // foo
~~~
<br/>
2. 用`對象`作為`對象屬性`的問題
~~~
// 創建一個空對象
let map = Object.create(null)
// 創建2個對象
let key1 = {}
let key2 = {}
// 用對象當做key值
map[key1] = 'foo'
console.log(map[key1]) // foo
console.log(map[key2]) // foo
~~~
<br/>
`key1`和`key2`會被轉換為`對象字符串`【Object,Object】,所以`map[key1]`和`map[key2]`引用的是同一個屬性,實際上就是一個`假值`。對于`Map集合`如果他的值是`假值`,會被自動轉換(強制轉換)成`布爾值false`,`強制轉換`本身沒有問題,但是應用到下面的場合就會有問題了
<br/>
~~~
// 創建一個對象
let map = Object.create(null);
map.count = 1;
// 這里本意是想檢查count是否存在,實際上檢查的是count值否等于0
if(map.count){
// 要執行的代碼
}
~~~
<br/>
在上面的例子中就有點讓人不解,我們到底是判斷的`map.count`是否存在,還是判斷的`map.count`的值是否`非零`,就會很讓人疑惑。 其實上面的例子中,由于值為`1`,所以判斷條件進入了`if`中,如果想判斷`對象的一個屬性值是否存在`盡量不要這樣寫,可以使用以下的幾個方法:
<br/>
3. 判斷對象屬性是否存在
~~~
1. 使用`in`關鍵字,該方法可以判斷對象的'自有屬性'和'繼承來的屬性'是否存在。
var o = { x: 1 }
console.log("x" in o) // true 自有屬性存在
console.log("y" in o) // false 沒有這個屬性
console.log("toString" in o) // true,是一個繼承屬性
2. 使用對象的'hasOwnProperty()'方法,該方法只能判斷'自有屬性是否存在',對于'繼承屬性會返回false'。
var o = { x: 1 };
o.hasOwnProperty("x"); // true,自有屬性中有x
o.hasOwnProperty("y"); // false,自有屬性中不存在y
o.hasOwnProperty("toString"); // false,這是一個繼承屬性,但不是自有屬性
~~~
- Javascript基礎篇
- Array數組
- 數組插入值
- filter()
- forEach()
- push()
- pop()
- unshift()
- shift()
- valueOf()
- 面向對象思想
- Javascript 面向對象編程(一):封裝
- Javascript面向對象編程(二):構造函數的繼承
- Javascript面向對象編程(三):非構造函數的繼承
- 解構
- 數組的解構賦值
- 對象的解構賦值
- 函數參數解構
- 字符串的解構賦值
- 數值和布爾值的解構賦值
- 圓括號問題
- 字符串.
- split()
- charAt()
- charCodeAt()
- concat()
- indexOf()
- lastIndexOf()
- match()
- replace()
- includes()
- 初識遞歸
- 渲染ul-li樹形結構
- 異步函數解決方案
- 1. callback回調函數
- 2. ES6 - Promise
- JavaScript高級程序設計(書)
- 在html中使用JavaScript
- script標簽的位置
- 延遲腳本
- 異步腳本
- <noscript>元素
- 基本概念
- 嚴格模式
- 變量詳解
- 數據類型
- typeof操作符
- undefined類型
- Null類型
- Boolean類型
- Number類型
- 深入了解ES6(書)
- var 、let 、 const
- 字符串與正則表達式
- 字符串
- 正則表達式
- 函數
- 函數形參默認值
- 使用不具名參數
- 函數構造器的增強能力
- 擴展運算符
- name屬性
- 明確函數的多重用途
- 塊級函數
- 箭頭函數
- 尾調用優化
- 擴展的對象功能
- 對象類別
- 對象字面量語法的擴展
- ES6對象新增方法
- 重復的對象屬性
- 自有屬性的枚舉順序
- 更強大的原型
- 解構:更方便的數據訪問
- 為什么要用解構?
- 對象解構
- 數組解構
- 混合解構
- 參數解構
- Symbol與Symbol屬性
- 創建Symbol
- Symbol的使用方法
- Symbol全局私有屬性
- Symbol與類型強制轉換
- Symbol屬性檢索
- Symbol的一些構造方法
- Set集合與Map集合
- Set集合
- Weak Set集合(弱引用Set集合)
- Map集合
- JS標準內置對象
- Object 構造函數及屬性
- Object 構造方法
- Symbol 內建對象類的函數及屬性
- Set 構造函數及屬性
- Weak Set 構造函數及屬性
- JS雜項
- 類數組對象
- Class類的理解和使用