ใน Javascript เทคนิคการทำสำเนาลึกนั้นขึ้นอยู่กับองค์ประกอบในอาเรย์ เริ่มกันเลย
องค์ประกอบสามประเภท
องค์ประกอบสามารถเป็นได้: ค่าตามตัวอักษร, โครงสร้างตัวอักษรหรือต้นแบบ
// Literal values (type1)
const booleanLiteral = true;
const numberLiteral = 1;
const stringLiteral = 'true';
// Literal structures (type2)
const arrayLiteral = [];
const objectLiteral = {};
// Prototypes (type3)
const booleanPrototype = new Bool(true);
const numberPrototype = new Number(1);
const stringPrototype = new String('true');
const arrayPrototype = new Array();
const objectPrototype = new Object(); // or `new function () {}`
จากองค์ประกอบเหล่านี้เราสามารถสร้างอาร์เรย์สามประเภท
// 1) Array of literal-values (boolean, number, string)
const type1 = [true, 1, "true"];
// 2) Array of literal-structures (array, object)
const type2 = [[], {}];
// 3) Array of prototype-objects (function)
const type3 = [function () {}, function () {}];
เทคนิคการทำสำเนาแบบลึกนั้นขึ้นอยู่กับชนิดของอาเรย์ทั้งสามชนิด
ขึ้นอยู่กับประเภทขององค์ประกอบในอาเรย์เราสามารถใช้เทคนิคต่าง ๆ เพื่อทำสำเนาลึก
อาร์เรย์ของตัวอักษรค่า (type1) , , และเทคนิคสามารถใช้ในการคัดลอกอาร์เรย์ลึกที่มีค่าที่แท้จริง (บูลจำนวนและสตริง) เท่านั้น ตำแหน่งที่ตัวดำเนินการ Spread มีประสิทธิภาพที่ดีที่สุด ( https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat )
[...myArray]
myArray.splice(0)
myArray.slice()
myArray.concat()
[...myArray]
อาร์เรย์ของตัวอักษรค่า (type1) และตัวอักษรโครงสร้าง (type2)เทคนิคสามารถนำมาใช้เป็นค่าที่แท้จริงสำเนาลึก (บูลจำนวนสตริง) และโครงสร้างตัวอักษร (อาร์เรย์วัตถุ) แต่ไม่ต้นแบบวัตถุ
JSON.parse(JSON.stringify(myArray))
อาร์เรย์ทั้งหมด (type1, type2, type3)สามารถใช้เทคนิค
jQuery ใน$.extend(myArray)
การคัดลอกอาเรย์ทุกประเภท ไลบรารี่อย่างUnderscoreและLo-dashนำเสนอฟังก์ชั่นสำเนาที่คล้ายกันกับjQuery $.extend()
แต่มีประสิทธิภาพต่ำกว่า เพิ่มเติมน่าแปลกใจที่$.extend()
มีประสิทธิภาพที่สูงกว่าJSON.parse(JSON.stringify(myArray))
เทคนิคhttp://jsperf.com/js-deep-copy/15
และสำหรับนักพัฒนาที่ไม่ได้อยู่ในห้องสมุดบุคคลที่สาม (เช่น jQuery) คุณสามารถใช้ฟังก์ชั่นที่กำหนดเองดังต่อไปนี้ ซึ่งมีประสิทธิภาพสูงกว่า $ .extend และคัดลอกอาร์เรย์ทั้งหมดลึก
function copy(aObject) {
if (!aObject) {
return aObject;
}
let v;
let bObject = Array.isArray(aObject) ? [] : {};
for (const k in aObject) {
v = aObject[k];
bObject[k] = (typeof v === "object") ? copy(v) : v;
}
return bObject;
}
ดังนั้นเพื่อตอบคำถาม ...
คำถาม
var arr1 = ['a','b','c'];
var arr2 = arr1;
ฉันรู้ว่า arr2 หมายถึงอาร์เรย์เดียวกันกับ arr1 แทนที่จะเป็น array ใหม่ที่เป็นอิสระ ฉันจะคัดลอกอาร์เรย์เพื่อรับสองอาร์เรย์อิสระได้อย่างไร
ตอบ
เนื่องจากarr1
เป็นอาร์เรย์ของค่าตัวอักษร (บูลีน, ตัวเลขหรือสตริง) คุณสามารถใช้เทคนิคการทำสำเนาแบบลึกที่กล่าวถึงข้างต้นซึ่งผู้ประกอบการสเปรด...
มีประสิทธิภาพสูงสุด
// Highest performance for deep copying literal values
arr2 = [...arr1];
// Any of these techniques will deep copy literal values as well,
// but with lower performance.
arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above
slice
และsplice
การดำเนินงานและผู้ประกอบการแพร่กระจายใหม่และArray.from
มีการดำเนินการช้ามาก ดูperfjs.fnfo