අන්තර්ජාලයේ බොහෝ විසඳුම් සමඟ ගැටළු කිහිපයක් තිබේ. එබැවින් පිළිගත් පිළිතුර පිළිගත නොහැක්කේ මන්ද යන්න ඇතුළත් පසු විපරමක් කිරීමට මම තීරණය කළෙමි.
ආරම්භක තත්වය
ජාවාස්ක්රිප්ට් එකක් එහි සියලුම දරුවන් සහ ඔවුන්ගේ දරුවන් සමඟ ගැඹුරින් පිටපත් කිරීමට මට අවශ්යය Object. නමුත් මම වගේ සාමාන්ය සංවර්ධක ක නැහැ පටන් මගේ Objectඇති සාමාන්ය properties , circular structuresපවා හා nested objects.
ඒ නිසා අපි පළමුව circular structureසහ nested objectපළමු නිර්මාණය කරමු .
function Circ() {
this.me = this;
}
function Nested(y) {
this.y = y;
}
සෑම දෙයක්ම Objectනමින් නම් කරමු a.
var a = {
x: 'a',
circ: new Circ(),
nested: new Nested('a')
};
ඊළඟට, අපට නම් කළ aහැකි විචල්යයකට පිටපත් කර එය bවිකෘති කිරීමට අවශ්යය .
var b = a;
b.x = 'b';
b.nested.y = 'b';
මෙහි සිදුවූයේ කුමක්දැයි ඔබ දන්නවා, එසේ නොවුවහොත් ඔබ මෙම ශ්රේෂ් question ප්රශ්නයට ගොඩ නොවන්නේය.
console.log(a, b);
a --> Object {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
b --> Object {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
දැන් අපි විසඳුමක් සොයා ගනිමු.
JSON
මම උත්සාහ කළ පළමු උත්සාහය වූයේ භාවිතා JSONකිරීමයි.
var b = JSON.parse( JSON.stringify( a ) );
b.x = 'b';
b.nested.y = 'b';
ඒ සඳහා වැඩි කාලයක් නාස්ති නොකරන්න, ඔබට ලැබෙනු TypeError: Converting circular structure to JSONඇත.
පුනරාවර්තන පිටපත (පිළිගත් "පිළිතුර")
පිළිගත් පිළිතුර දෙස බලමු.
function cloneSO(obj) {
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = cloneSO(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
var copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
හොඳයි, හෙහ්? එය වස්තුවේ පුනරාවර්තන පිටපතක් වන අතර වෙනත් වර්ගද හසුරුවයි Date, නමුත් එය අවශ්යතාවයක් නොවීය.
var b = cloneSO(a);
b.x = 'b';
b.nested.y = 'b';
පුනරාවර්තනය සහ circular structuresහොඳින් ක්රියා නොකරයි ...RangeError: Maximum call stack size exceeded
දේශීය විසඳුම
මගේ සම-සේවකයා සමඟ වාද කිරීමෙන් පසු, මගේ ලොක්කා අපෙන් ඇසුවේ කුමක්දැයි විමසූ අතර, ඔහු ගොග්ලිං කිරීමෙන් පසු සරල විසඳුමක් සොයා ගත්තේය . එය හැඳින්වේ Object.create.
var b = Object.create(a);
b.x = 'b';
b.nested.y = 'b';
මෙම විසඳුම කලකට පෙර ජාවාස්ක්රිප්ට් වෙත එකතු කරන ලද අතර එය හසුරුවයි circular structure.
console.log(a, b);
a --> Object {
x: "a",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
b --> Object {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
... ඔබට පෙනේ, එය ඇතුළත කැදැලි ව්යුහය සමඟ ක්රියා කළේ නැත.
දේශීය විසඳුම සඳහා පොලිෆිල්
Object.createIE 8 මෙන් පැරණි බ්රව්සරයේ පොලිෆිල් එකක් තිබේ. එය මොසිල්ලා විසින් නිර්දේශ කරන ලද දෙයක් වන අතර ඇත්ත වශයෙන්ම එය පරිපූර්ණ නොවන අතර දේශීය විසඳුම හා සමාන ගැටළුවක් ඇති කරයි .
function F() {};
function clonePF(o) {
F.prototype = o;
return new F();
}
var b = clonePF(a);
b.x = 'b';
b.nested.y = 'b';
මම Fවිෂය පථයෙන් පිටත තබා ඇති නිසා අපට instanceofපවසන දේ බැලීමට අපට හැකිය.
console.log(a, b);
a --> Object {
x: "a",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
b --> F {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
console.log(typeof a, typeof b);
a --> object
b --> object
console.log(a instanceof Object, b instanceof Object);
a --> true
b --> true
console.log(a instanceof F, b instanceof F);
a --> false
b --> true
ස්වදේශීය විසඳුම හා සමාන ගැටළුවක් , නමුත් ටිකක් නරක ප්රතිදානය.
වඩා හොඳ (නමුත් පරිපූර්ණ නොවේ) විසඳුම
වටේ කැණීමේදී මට සමාන ප්රශ්නයක් හමු විය ( ජාවාස්ක්රිප්ට් හි, ගැඹුරු පිටපතක් සිදු කරන විට, දේපලක් “මෙය” වීම නිසා මම චක්රයක් වළක්වා ගන්නේ කෙසේද? ) නමුත් මේ සඳහා වඩා හොඳ විසඳුමක් ඇත.
function cloneDR(o) {
const gdcc = "__getDeepCircularCopy__";
if (o !== Object(o)) {
return o; // primitive value
}
var set = gdcc in o,
cache = o[gdcc],
result;
if (set && typeof cache == "function") {
return cache();
}
// else
o[gdcc] = function() { return result; }; // overwrite
if (o instanceof Array) {
result = [];
for (var i=0; i<o.length; i++) {
result[i] = cloneDR(o[i]);
}
} else {
result = {};
for (var prop in o)
if (prop != gdcc)
result[prop] = cloneDR(o[prop]);
else if (set)
result[prop] = cloneDR(cache);
}
if (set) {
o[gdcc] = cache; // reset
} else {
delete o[gdcc]; // unset again
}
return result;
}
var b = cloneDR(a);
b.x = 'b';
b.nested.y = 'b';
ප්රතිදානය දෙස බලමු ...
console.log(a, b);
a --> Object {
x: "a",
circ: Object {
me: Object { ... }
},
nested: Object {
y: "a"
}
}
b --> Object {
x: "b",
circ: Object {
me: Object { ... }
},
nested: Object {
y: "b"
}
}
console.log(typeof a, typeof b);
a --> object
b --> object
console.log(a instanceof Object, b instanceof Object);
a --> true
b --> true
console.log(a instanceof F, b instanceof F);
a --> false
b --> false
අවශ්යතා ගැලපේ, නමුත් වෙනස් instanceකිරීම nestedසහ වෙනස් කිරීම ඇතුළුව තවමත් කුඩා ගැටළු කිහිපයක් circතිබේ Object.
පත්රයක් බෙදා ගන්නා ගස්වල ව්යුහය පිටපත් නොකෙරේ, ඒවා ස්වාධීන කොළ දෙකක් බවට පත්වේ:
[Object] [Object]
/ \ / \
/ \ / \
|/_ _\| |/_ _\|
[Object] [Object] ===> [Object] [Object]
\ / | |
\ / | |
_\| |/_ \|/ \|/
[Object] [Object] [Object]
නිගමනය
පුනරාවර්තනය සහ හැඹිලිය භාවිතා කරන අවසාන විසඳුම හොඳම නොවිය හැකි නමුත් එය වස්තුවේ සැබෑ ගැඹුරු පිටපතකි. එය සරල හසුරුවන properties, circular structuresසහ nested objectඋත්සහය අතර, නමුත් එය අවුල් කරනු ඔවුන් උදාහරණයක් දක්වා.
jsfiddle