Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
家好,很高興又見面了,我是姜茶的編程筆記,我們一起學習前端相關領域技術,共同進步,也歡迎大家關注、點贊、收藏、轉發,您的支持是我不斷創作的動力
在 JavaScript 中,Array.prototype.map 是一個常用的方法,它對數組的每個元素調用提供的函數,并返回一個新數組,包含函數的返回值。為了更好地理解其內部機制,今天我們將從零開始,實現一個自定義的 map 方法,并詳細解析其實現步驟。
首先,我們創建一個 myMap 方法,將其添加到 Array.prototype 上。這個方法接受兩個參數:一個回調函數 callback 和一個可選的 thisArg 參數。callback 函數將對數組的每個元素進行操作,thisArg 是執行回調函數時的 this 值。
Array.prototype.myMap=function(callback, thisArg) {
// 將傳入的數組轉換為對象
const O=Object(this);
// 獲取數組的長度
const len=O.length >>> 0;
// 如果 callback 不是函數,則拋出 TypeError
if (typeof callback !=='function') {
throw new TypeError(callback + ' is not a function');
}
// 創建一個新的數組,用于存儲映射結果
const result=new Array(len);
// 遍歷數組并應用回調函數
for (let i=0; i < len; i++) {
// 只有當元素在數組中存在時才進行映射
if (i in O) {
// 調用回調函數,傳遞 thisArg 作為 this 值,并傳遞當前元素、索引、數組本身
result[i]=callback.call(thisArg, O[i], i, O);
}
}
return result;
};
讓我們逐步解析這個實現。
我們首先將 this 轉換為一個對象,以便在方法中使用:
const O=Object(this);
使用 >>> 0 操作符將長度轉換為無符號整數,確保其為正整數:
const len=O.length >>> 0;
如果 callback 不是函數,則拋出一個 TypeError:
if (typeof callback !=='function') {
throw new TypeError(callback + ' is not a function');
}
我們創建一個與原數組長度相同的新數組,用于存儲映射結果:
const result=new Array(len);
使用 for 循環遍歷數組的每個索引。如果當前索引存在于數組中,則調用回調函數,并將結果存儲在 result 數組中:
for (let i=0; i < len; i++) {
if (i in O) {
result[i]=callback.call(thisArg, O[i], i, O);
}
}
最后,我們返回存儲映射結果的 result 數組:
return result;
下面是一個示例,展示如何使用自定義的 myMap 方法:
const numbers=[1, 2, 3, 4, 5];
const doubled=numbers.myMap(x=> x * 2);
console.log(doubled); // 輸出 [2, 4, 6, 8, 10]
在這個示例中,我們將 numbers 數組中的每個元素都乘以 2,并將結果存儲在 doubled 數組中。結果輸出為 [2, 4, 6, 8, 10],這與內置的 Array.prototype.map 方法的行為一致。
通過實現自定義的 map 方法,我們深入理解了 JavaScript 中數組的操作方式。希望你可以更好地掌握 map 方法的內部機制,并提升你的 JavaScript 編程技巧。
如果你有任何問題或建議,歡迎在評論區留言交流!祝你編程愉快!
Map 對象
Map 對象表示 HTML <map> 元素。
訪問 Map 對象
你可以使用 getElementById() 訪問 <map> 元素:
var x=document.getElementById("myMap");
創建 Map 對象
你可以通過使用 document.createElement() 方法創建 <map> 元素:
var x=document.createElement("MAP");
Map 對象集合
集合 | 描述 |
---|---|
areas | 返回圖象地圖中所有 <area> 元素的集合 |
images | 返回所有與圖象地圖相關 <img> 和 <object> 元素的集合 |
Map 對象熟悉
屬性 | 描述 |
---|---|
name | 設置或返回圖像地圖的 name 屬性值 |
標準屬性和事件
Map 對象同樣支持標準的 屬性 和 事件。
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
ap、filter、reduce都是高階函數,它們的功能非常強大,可以搭配箭頭函數來完成復雜的數組數據處理。關于它們的用法很多人寫過,但少有人寫結合案例來寫。在這里我會對這3個函數的用法結合案例來詳細講述,并額外寫了for循環版本用來幫助理解。
要詳細講述這3個高階函數的用法必須結合實際案例來講。現在有一個這樣的數組,這個數組是任務清單:
let todo=[
{id: 1, name: "吃飯", done: true},
{id: 2, name: "睡覺", done: true},
{id: 3, name: "編程", done: false},
{id: 4, name: "寫作", done: false},
{id: 5, name: "逛街", done: true},
]
參數:只接收一個參數,必須是處理數據的函數。
作用:對數組成員調用傳來的參數函數,進行處理后給出返回值。
返回值:返回由返回值構成的新數組。
需求
寫一個可以更新todo數組數據的函數,例如對todo數組中id為3的done字段更新為true。
代碼
map版本:
function updateTodo(arr, id, state) { // arr是數組,id是要處理的id,state是要更新的狀態
return arr.map(item=> {
if (item.id===id) return {...item, done: state} // 若找到指定id,那么更新數據
else return item // 若沒找到指定id,返回原值
})
}`
for循環版本:
function updateFor(arr, id, state) {
let newArr=[]
for (let i=0; i < arr.length; i++) {
if (arr[i].id===id) newArr[i]={...arr[i], done: state}
else newArr[i]=arr[i]
}
return newArr
}`
測試
const newTodo1=updateTodo(todo,3,true) // 檢查運行結果可以看到id是3的記錄的狀態已更新為true
todo=newTodo1 // 將新內容更新到原數組
const newTodo2=updateFor(todo,1,false) // 檢查運行結果可以看到id是1的記錄的狀態已更新為false
todo=newTodo2 // 將新內容更新到原數組`
參數:只接收一個參數,必須是處理數據的函數。
作用:對數組成員調用傳來的參數函數,進行處理后給出true或false的返回值。
返回值:返回由返回值為true的數組成員構成的新數組。
需求
寫一個可以刪除todo數組指定行的函數,例如將todo數組中id為3那行數據刪除。
代碼
filter版本:
function deleteTodo(arr, id) { // arr是數組,id是要處理的id,state是要更新的狀態
return arr.filter(item=> {
if (item.id===id) return false // 若找到指定id,那么返回false,表示該行數據不要
else return true // 其他行數據返回true,表示該行數據需要
})
}`
for循環版本:
function deleteFor(arr, id) {
let newArr=[]
for (let i of arr) {
if (i.id !==id) newArr.push(i)
}
return newArr
}`
測試
const newTodo1=deleteTodo(todo,3) // 檢查運行結果可以看到id是3的記錄不存在
todo=newTodo1 // 將新內容更新到原數組
const newTodo2=deleteFor(todo,4) // 檢查運行結果可以看到id是4的記錄不存在
todo=newTodo2 // 將新內容更新到原數組
參數:接收兩個參數,第一個必須是處理數據的函數,第二個是初始值(數字型)。注意:該參數函數可以接收到4個參數,第一個參數是累加值,第二個參數是當前的數組成員,第三個參數是索引,第四個參數是數組,一般后2個可忽略。
作用:對數組成員調用傳來的參數函數,進行處理后給出數字,然后將該數字累加到累加值上。
返回值:返回累加值。
需求
寫一個可以統計todo數組中done為true的記錄數量的函數。
代碼
reduce版本:
function countTodo(arr) {
return arr.reduce((total,item)=> total+(item.done?1:0),0)
}
for循環版本:
function countFor(arr) {
let count=0
for (let i of arr) {
if (i.done) count++
}
return count
}
測試
const count1=countTodo(todo) // 檢查運行結果可以看到統計結果是3
const count2=countFor(todo) // 檢查運行結果可以看到統計結果也是3
寫完了,希望對還沒徹底掌握map、filter、reduce這3個高階函數用法的朋友能有所幫助。請參考數據、需求和代碼,嘗試理解,自己敲一遍,然后嘗試自己寫一下。這樣就能徹底掌握map、filter、reduce這3個常用的高階函數了。
請注意:這3個函數底層有優化,用它們比自己寫循環的運行效率要高,代碼也更簡潔。它們都是前端程序員處理數據時經常要用到的!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。