第二週,慢慢積累,作好準備,迎接蛻變
node
1. 介紹下 Set、Map、WeakSet 和 WeakMap 的區別?
const set = new Set([1,2,2,3,3,3])
[...set] // [1,2,3]
複製代碼
屬性數組
操做方法bash
遍歷方法數據結構
const a = [[1, 2], [3, 4]];
const ws = new WeakSet(a); // WeakSet {[1, 2], [3, 4]}
複製代碼
方法函數
ES6 提供了 Map 數據結構。它相似於對象,也是鍵值對的集合,可是「鍵」的範圍不限於字符串,各類類型的值(包括對象)均可以看成鍵。能夠遍歷,方法不少,能夠和各類數據格式轉換
ui
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
const map = new Map([
['name', '張三'],
['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "張三"
map.has('title') // true
map.get('title') // "Author"
複製代碼
任何具備 Iterator 接口、且每一個成員都是一個雙元素的數組的數據結構均可以看成Map構造函數的參數。這就是說,Set和Map均可以用來生成新的 Map。spa
const set = new Set([
['foo', 1],
['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3
複製代碼
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同於使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
複製代碼
Map 結構轉爲數組結構,比較快速的方法是使用擴展運算符(...)。例如prototype
const map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()] // [1,2,3]
複製代碼
WeakMap的專用場合就是,它的鍵所對應的對象,可能會在未來消失。WeakMap結構有助於防止內存泄漏。
指針
2. 介紹下深度優先遍歷和廣度優先遍歷,如何實現?
這是一個須要遍歷的DOM樹code
<div id="parent">
<div id="child-1">
<div id="child-1-1">
<div id="child-1-1-1"></div>
<div id="child-1-1-2"></div>
<div id="child-1-1-3"></div>
</div>
<div id="child-1-2">
<div id="child-1-2-1"></div>
<div id="child-1-2-2"></div>
</div>
<div id="child-1-3"></div>
</div>
<div id="child-2"></div>
<div id="child-3"></div>
</div>
複製代碼
let deepTraversal = (node) => {
let nodes = []
if (node !== null) {
nodes.push(node)
let children = node.children
for (let i = 0; i < children.length; i++) {
nodes = nodes.concat(deepTraversal(children[i]))
}
}
return nodes
}
let res = document.querySelector('#parent')
console.log(deepTraversal(res))
複製代碼
結果
假設初始狀態是圖中全部頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點而後依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中全部和v有路徑相通的頂點都被訪問到。若此時尚有其餘頂點未被訪問到,則另選一個未被訪問的頂點做起始點,重複上述過程,直至圖中全部頂點都被訪問到爲止。
let widthTraversal = (node) => {
let nodes = []
let stack = []
if (node) {
stack.push(node)
while (stack.length) {
let item = stack.shift()
let children = item.children
nodes.push(item)
// 隊列,先進先出
// nodes = [] stack = [parent]
// nodes = [parent] stack = [child1,child2,child3]
// nodes = [parent, child1] stack = [child2,child3,child1-1,child1-2]
// nodes = [parent,child1,child2]
for (let i = 0; i < children.length; i++) {
stack.push(children[i])
}
}
}
return nodes
}
複製代碼
結果
從圖中某頂點v出發,在訪問了v以後依次訪問v的各個不曾訪問過的鄰接點,而後分別從這些鄰接點出發依次訪問它們的鄰接點,並使得「先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點被訪問,直至圖中全部已被訪問的頂點的鄰接點都被訪問到。 若是此時圖中尚有頂點未被訪問,則須要另選一個不曾被訪問過的頂點做爲新的起始點,重複上述過程,直至圖中全部頂點都被訪問到爲止。
3. 淺拷貝和深拷貝
引用網上一張圖片說明一下數據類型和淺拷貝和深拷貝的關係
JS中的值有兩種類型:
存放位置:
賦值操做、淺拷貝與深拷貝的關係
var a = 1
var b = a
a++
console.log(a) // 2
console.log(b) // 1
複製代碼
var a = {num:1}
var b = a
a.num = 2
console.log(a.num) // 2
console.log(b.num) // 2
複製代碼
將源對象拷貝到目標對象中,但不包括源對象的子對象
將源對象拷貝到目標對象中,包括源對象的子對象
對於複雜基本類型的數據,三種操做的對比
操做 | 和原數據是否指向同一對象 | 第一層數據爲基本數據類型 | 原數據中包含子對象 |
---|---|---|---|
賦值 | 是 | 改變會使原數據改變 | 改變會使原數據改變 |
淺拷貝 | 否 | 改變不會使原數據改變 | 改變會使原數據改變 |
深拷貝 | 否 | 改變不會使原數據改變 | 改變不會使原數據改變 |
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
複製代碼
JSON.parse(JSON.stringify(obj))實現深拷貝是有侷限性的,當數據中有function或undefined等數據時,是不能實現的。
function deepClone(obj) {
// 由於typeof null == "object" 但 null並非對象,是基本類型
if (obj == null) return
var res = Array.isArray(obj) ? [] : {}
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if ( typeof obj[key] == "object" ) {
res[key] = deepClone(obj[key])
} else {
res[key] = obj[key]
}
}
}
return res
}
複製代碼
驗證一下
var source = {
name: 'source',
do: function (n) {
console.log(n)
},
obj: {
name: '子對象obj'
}
}
var target = deepClone(source)
target.name = 'target'
target.do = function (n) {
console.log(n * 2)
}
target.obj.name = '拷貝子對象成功'
console.log(source)
console.log(target)
複製代碼
能夠看到修改了拷貝對象的子對象並無對源對象產生影響,拷貝成功。
歡迎指正和交流