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
這是在ES6中出現(xiàn)的新的運算符,自從出現(xiàn)以來,它已經成為最受歡迎的方法之一,它的語法實在是太簡潔
numbers=[1, 2, 3]; numbersCopy=[...numbers];
注意:它不能安全的復制多維數(shù)組,數(shù)組/對象是通過引用復制而不是通過值復制
正例:
numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4]
反例:
nestedNumbers=[[1], [2]]; numbersCopy=[...nestedNumbers]; numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]]
由于函數(shù)式編程的流行,現(xiàn)在應該用的比較少了
numbers=[1, 2, 3]; numbersCopy=[]; for (i=0; i < numbers.length; i++) { numbersCopy[i]=numbers[i]; }
注意:它也不能安全地復制多維數(shù)組。因為使用=運算符,因此它將通過引用而不是值來分配對象/數(shù)組。
正例:
numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4]
反例:
nestedNumbers=[[1], [2]]; numbersCopy=[]; for (i=0; i < nestedNumbers.length; i++) { numbersCopy[i]=nestedNumbers[i]; } numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy);
和for循環(huán)類似
numbers=[1, 2, 3]; numbersCopy=[]; i=-1; while (++i < numbers.length) { numbersCopy[i]=numbers[i]; }
注意:它也通過引用而不是按值分配對象/數(shù)組。
正例:
numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4]
反例:
nestedNumbers=[[1], [2]]; numbersCopy=[]; i=-1; while (++i < nestedNumbers.length) { numbersCopy[i]=nestedNumbers[i]; } numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]]
map會將數(shù)組轉換成為另一個數(shù)組又同時保留結構的方法
numbers=[1, 2, 3]; double=(x)=> x * 2; numbers.map(double);
復制數(shù)組就更簡單了
numbers=[1, 2, 3]; numbersCopy=numbers.map((x)=> x);
注意:它同樣也通過引用而不是按值分配對象/數(shù)組。
和map一樣,接受一個函數(shù)組作為參數(shù),但是它會通過傳遞的函數(shù)過濾和篩選,這樣不能保證得到數(shù)組長度不變,比如篩選出數(shù)組中的偶數(shù)
[1, 2, 3].filter((x)=> x % 2===0) // [2]
復制數(shù)組
numbers=[1, 2, 3]; numbersCopy=numbers.filter(()=> true);
注意:它同樣也通過引用而不是按值分配對象/數(shù)組。
reduce 在循環(huán)列表時轉換初始值
numbers=[1, 2, 3]; numbersCopy=numbers.reduce((newArray, element)=> { newArray.push(element); return newArray; }, []);
注意:它同樣也通過引用而不是按值分配對象/數(shù)組。
slice需要你傳遞開始索引和結束索引
[1, 2, 3, 4, 5].slice(0, 3); // [1, 2, 3] // 0到3索引,得到1,2,3,不包括4
如果只想復制,不需要傳遞任何參數(shù)即可
numbers=[1, 2, 3, 4, 5]; numbersCopy=numbers.slice(); // [1, 2, 3, 4, 5]
注意:它同樣也通過引用而不是按值分配對象/數(shù)組。
組合它們可以將對象轉換為字符串,然后反轉該過程可以創(chuàng)建全新的數(shù)據(jù)結構。
nestedNumbers=[[1], [2]]; numbersCopy=JSON.parse( JSON.stringify(nestedNumbers) ); numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1], [2]] // [[1, 300], [2]] // 兩個數(shù)組是分開的
注意:它是安全的復制方法
concat是數(shù)組之間相連接,例如
[1, 2, 3].concat(4); // [1, 2, 3, 4] [1, 2, 3].concat([4, 5]); // [1, 2, 3, 4, 5]
如果只是單純的復制,那你可以不傳遞任何參數(shù)或者傳遞一個空數(shù)組即可
[1, 2, 3].concat(); // [1, 2, 3] [1, 2, 3].concat([]); // [1, 2, 3]
注意:它同樣也通過引用而不是按值分配對象/數(shù)組。
可以將任何可迭代對象轉換為數(shù)組,如下
numbers=[1, 2, 3]; numbersCopy=Array.from(numbers) // [1, 2, 3]
注意:它同樣也通過引用而不是按值分配對象/數(shù)組。
本文著重探討的是數(shù)組的復制,這些方法都可以用來做數(shù)組的拷貝,各有好壞,其實還有其他的一些方法來完成數(shù)組的復制,本文就介紹到這,如果對你有幫助,請點個關注吧!
在前端開發(fā)的浩瀚海洋中,JavaScript猶如一盞明燈,照亮了網頁交互的每一個角落。作為現(xiàn)代Web開發(fā)不可或缺的一部分,掌握JavaScript的核心概念是每個前端工程師的基本功。本文旨在深入解析JavaScript中的幾個關鍵點——二維數(shù)組的操作、引用類型的特性以及深克隆與淺克隆的區(qū)別,通過理論結合實踐,幫助初學者構建堅實的基礎。
二維數(shù)組是數(shù)組元素本身也是數(shù)組的數(shù)據(jù)結構,常用于模擬表格或矩陣。它們在處理網格布局、游戲地圖等場景時尤為有用。
示例代碼:
let matrix=[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
console.log(matrix[1][2]); // 輸出 6
JavaScript中的對象、數(shù)組、函數(shù)等都屬于引用類型。它們存儲的是指向數(shù)據(jù)的引用,而非數(shù)據(jù)本身,這意味著多個變量可以引用同一個對象。
示例代碼:
let obj1={ value: 10 };
let obj2=obj1;
obj2.value=20;
console.log(obj1.value); // 輸出 20
克隆是在不改變原對象的情況下復制對象的過程。淺克隆僅復制對象的第一層屬性,而深克隆會遞歸復制所有層級的屬性。
示例代碼:
function shallowClone(obj) {
return Object.assign({}, obj);
}
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
考慮一個游戲開發(fā)場景,二維數(shù)組可以用來表示游戲地圖,其中每個元素代表地圖上的一個位置。
示例代碼:
let gameMap=[
['water', 'land', 'land'],
['land', 'forest', 'mountain'],
['mountain', 'water', 'land']
];
在事件監(jiān)聽器中傳遞對象時,利用引用類型可以實時反映對象狀態(tài)的變化。
示例代碼:
let data={ count: 0 };
document.getElementById('myButton').addEventListener('click', function() {
data.count++;
console.log(data.count);
});
在需要保持數(shù)據(jù)原始狀態(tài)不變的場景下,如表單的初始值保存,使用深克隆可以創(chuàng)建一份完全獨立的數(shù)據(jù)副本。
示例代碼:
let originalFormValues={ name: 'John', age: 30 };
let formBackup=deepClone(originalFormValues);
深克隆會消耗更多的計算資源,對于復雜的對象,應評估是否真的需要復制每一層。
對于包含函數(shù)或循環(huán)引用的對象,使用JSON.parse和JSON.stringify進行深克隆可能失敗,這時需要尋找更專業(yè)的克隆庫或自定義克隆函數(shù)。
可以使用typeof檢查,但更準確的方法是使用Object.prototype.toString.call()。
示例代碼:
function isObject(value) {
return Object.prototype.toString.call(value)==='[object Object]';
}
確保在函數(shù)內部使用局部變量,避免直接修改傳入的引用類型參數(shù)。
掌握JavaScript中的二維數(shù)組、引用類型和克隆技巧是構建高效、健壯的前端應用程序的關鍵。隨著Web技術的不斷演進,這些基礎知識將為開發(fā)者提供強大的工具箱,應對未來可能出現(xiàn)的各種挑戰(zhàn)。繼續(xù)深化你的JavaScript技能,探索更多高級主題,如異步編程、模塊化設計和性能優(yōu)化,將使你在前端開發(fā)領域更加游刃有余。
意味著,當您嘗試使用 const newArray=oldArray 復制它時,它將復制對原始數(shù)組的引用而不是復制值。
const beers=['', '', ''];
const beersCopy=beers;
console.log(beers===beersCopy);
// The console output will be true, because it's pointing to the exact value in memory.
淺拷貝數(shù)組
當拷貝或克隆數(shù)組時,值的數(shù)據(jù)類型是決定使用何種方法的關鍵。
如果您的數(shù)組僅包含原始不可變值(數(shù)字、布爾值、字符串等),您可以使用以下方法。
我們簡單地遍歷原始數(shù)組并將每個元素推送到新數(shù)組。
const arr=[1, 2, 3];
const newArr=[];
for (let i=0; i < arr.length; i++) {
newArr.push(arr[i]);
}
…(展開)
展開運算符是最快的方法之一,是在 ES6 中引入的。它簡潔明了,是一種本地方法(對不起 lodash)。
const arr=[1, 2, 3];
const newArr=[...arr];
.slice()
slice() 方法將數(shù)組的一部分的淺拷貝返回到從頭到尾選擇的新數(shù)組對象中 arr.slice([start[, end]])。原始數(shù)組不會被修改。這是復制數(shù)組的最快方法。
const arr=[1, 2, 3];
const newArr=arr.slice();
Array.from
Array.from() 靜態(tài)方法從類數(shù)組或可迭代對象(Map 或 Set)創(chuàng)建一個新的淺拷貝 Array 實例。
它還采用可選的映射函數(shù)作為第二個參數(shù) Array.from(arrayLike [, mapFn [, thisArg]])。
const arr=[1, 2, 3];
const newArr=Array.from(arr);
_.clone()
lodash 的 _.clone(value) 方法創(chuàng)建了一個值的淺克隆。它表現(xiàn)良好,如果您已經在您的應用程序中使用 lodash,它是一個可行的選擇。
// import lodash
const _=require('lodash');
const arr=[1, 2, 3];
const newArr=_.clone(arr);
Deep Copy Arrays
上面的所有方法都會創(chuàng)建數(shù)組的淺表副本。如果您將對象作為數(shù)組項,并且嘗試進行淺拷貝,則將復制實際數(shù)組,但底層對象將通過引用傳遞給新數(shù)組。
讓我們通過一個代碼示例來看一下這個問題。
const arr=[
{
name: 'mario',
food: 'pizza',
},
{
name: 'luigi',
food: 'spaghetti',
},
];
const arrCopy=[...arr];
console.log(arr===arrCopy);
// 這將返回 false,因為數(shù)組已被復制(淺復制),內存中的新引用。
console.log(arr[0]===arrCopy[0]);
// 這將返回 true,因為引用指向內存中的相同位置。
有幾種方法可以創(chuàng)建深度克隆。
jQuery.extend()
_.clonedeep()
JSON (stringify/parse)
jQuery.extend()
如果您仍在項目中使用 jQuery,則可以使用 jQuery 的擴展方法。
const arr=[
{
name: 'mario',
food: 'pizza',
},
{
name: 'luigi',
food: 'spaghetti',
},
];
const arrCopy=jQuery.extend(true, [], arr);
console.log(arr===arrCopy);
// This will return false, because the array has been copied (new reference in memory).
console.log(arr[0]===arrCopy[0]);
// This will return false, because the reference points to a new one in memory.
_.cloneDeep()
來自 Lodash 的方法 _.cloneDeep(value) 做的事情與 _.clone() 完全相同,除了它遞歸地克隆數(shù)組中的所有內容。
const arr=[
{
name: 'mario',
food: 'pizza',
},
{
name: 'luigi',
food: 'spaghetti',
},
];
// import lodash
const _=require('lodash');
const arrCopy=_.cloneDeep(arr);
console.log(arr===arrCopy);
// This will return false, because the array has been copied (new reference in memory).
console.log(arr[0]===arrCopy[0]);
// This will return false, because the reference points to a new one in memory.
JSON 方法
JavaScript 提供了用于序列化和反序列化的原生方法,基本上是將大多數(shù)數(shù)據(jù)類型轉換為 JSON 字符串,然后將有效的 JSON 字符串轉換為對象。
它可以這樣使用:
const arr=[
{
name: 'mario',
food: 'pizza',
},
{
name: 'luigi',
food: 'spaghetti',
},
];
const arrCopy=JSON.parse(JSON.stringify(arr));
console.log(arr===arrCopy);
// This will return false, because the array has been copied (new reference in memory).
console.log(arr[0]===arrCopy[0]);
// This will return false, because the reference points to a new one in memory.
使用這種方法有一些優(yōu)點和缺點。一個優(yōu)點是它不需要像 Lodash 這樣的第三方庫。缺點是提供的數(shù)組數(shù)據(jù)需要可序列化,通過 JSON 進行序列化和反序列化需要一些時間,因此這不是最快的方法。
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。