這是《JS 深刻淺出》第八課的部分講義前端
今天的課的主要內容有面試
先從最簡單的數組操做開始:算法
var array = ['a','b','c']
array.join('-') // 結果是 'a-b-c'
複製代碼
咱們畫一下內存圖:數組
因此咱們能夠大膽猜想 array.join 的源代碼大概是這樣的bash
Array.prototype.join = function(char){
let result = this[0] || ''
let length = this.length
for(let i=1; i< length; i++){
result += char + this[i]
}
return result
}
複製代碼
this 就是 array,由於你使用 array.join('-') 來調用 join 的(隱式指定this)函數
接下來研究第二個數組操做ui
array.slice(beginIndex, endIndex)
複製代碼
顯而易猜,源碼大概大概大概是這樣的this
Array.prototype.slice = function(begin, end){
let result = []
begin = begin || 0
end = end || this.length
for(let i = begin; i< end; i++){
result.push(this[i])
}
return result
}
複製代碼
因而不少前端用 slice 來將僞數組,轉化成數組spa
array = Array.prototye.slice.call(arrayLike)
或者
array = [].slice.call(arrayLike)
複製代碼
ES 6 看不下去這種蹩腳的轉化方法,出了一個新的 APIprototype
array = Array.from(arrayLike)
複製代碼
專門用來將僞數組轉化成真數組。
P.S. 僞數組與真數組的區別就是:僞數組的原型鏈中沒有 Array.prototype,而真數組的原型鏈中有 Array.prototype。所以僞數組沒有 pop、join 等屬性。
我據說大部分的語言內置的 sort 方法都是快速排序算法。咱們就簡化成選擇排序吧
Array.prototype.sort = function(fn){
fn = fn || (a,b)=> a-b
let roundCount = this.length - 1 // 比較的輪數
for(let i = 0; i < roundCount; i++){
let minIndex = this[i]
for(let k = i+1; k < this.length; k++){
if( fn.call(null, this[k],this[i]) < 0 ){
[ this[i], this[k] ] = [ this[k], this[i] ]
}
}
}
}
複製代碼
fn.call(null, this[k], this[i]) 決定了第 k 項和第 i 項的先後(大小)關係。
fn 爲 (a,b) => a-b 表示啥?fn 爲 (a,b) => b-a 又表示啥?
不重要,由於若是前者不符合你的需求,那麼後者必定符合你的需求,你只須要試兩邊就知道用哪個了。
Array.prototype.forEach = function(fn){
for(let i=0;i<this.length; i++){
if(i in this){
fn.call(undefined, this[i], i, this)
}
}
}
複製代碼
forEach 和 for 的區別主要有兩個:
Array.prototype.map = function(fn){
let result = []
for(let i=0;i<this.length; i++){
if(i in this) {
result[i] = fn.call(undefined, this[i], i, this)
}
}
return result
}
複製代碼
map 和 forEach 功能差很少,區別只有返回值而已。 接下來是 filter
Arra.prototype.filter = function(fn){
let result = []
let temp
for(let i=0;i<this.length; i++){
if(i in this) {
if(temp = fn.call(undefined, this[i], i, this) ){
result.push(this[i])
}
}
}
return result
}
複製代碼
fn.call() 返回真值就 push 到返回值,沒返回真值就不 push。 接下來是 reduce
Arra.prototype.reduce = function(fn, init){
let result = init
for(let i=0;i<this.length; i++){
if(i in this) {
result = fn.call(undefined, result, this[i], i, this)
}
}
return result
}
複製代碼
map、filter 和 reduce 的區別:
map、filter 和 reduce 的聯繫:
array2 = array.map( (v) => v+1 )
能夠寫成
array2 = array.reduce( (result, v)=> {
result.push(v + 1)
return result
}, [ ] )
複製代碼
array2 = array.filter( (v) => v % 2 === 0 )
能夠寫成
array2 = array.reduce( (result, v)=> {
if(v % 2 === 0){ result.push(v) }
return result
}, [])
複製代碼
Underscore 是一個集合操做的庫(當時 JS 沒有 Set,因此集合指的是數組和對象) 主要有六類 API:
後面講義需收費觀看。課後還有兩道經典面試題。
歡迎購買《JS 深刻淺出》。