Javascript:对象的 setter 和 getter 在克隆/复制/扩展后丢失
Javascript: object's setter and getter is lost after clonning / copying / extending
我希望能够复制一个保持 getter and setter 功能的对象。
注意:这个问题是关于 angularjs 但它也可能适用于许多其他框架。
代码位于:https://jsfiddle.net/vwb04d4f/2/
function out(str) {
document.getElementById('body').innerHTML += str + "<br>";
}
var SomeObj = function () {
var obj = {
_val: 0,
set val(value) {
out("Set: " + value);
this._val = value;
},
get val() {
return this._val;
}
}
return obj;
};
var sObj = new SomeObj();
sObj.val = 100;
var sCopy = angular.copy(sObj);
sCopy.val = 200;
out("Value:" + sCopy.val);
var sExt = angular.extend(sObj);
sExt.val = 300;
out("Value: " + sObj.val);
输出:
Set: 100
Value:200
Set: 300
Value: 300
为什么 "set val" 在 "angular.copy" 之后不再触发?如您所见,该值已正确存储。
"angular.extend" 保留引用,因此更新 sExt 将更新 sObj,这是我不想要的。
我在将范围对象传递到控制器之前复制它(模态):
$modal.open({
animation: true,
templateUrl: '/html/settings.html',
controller: 'ModalInstanceCtrl',
backdrop: false,
resolve: {
config: function() {
var cfgcpy = {};
angular.copy($scope.config, cfgcpy);
return cfgcpy;
}
}
}).result.then(function(res){
ok_func(res);
close_func();
}, function() {
close_func();
});
angular.module('app').controller('ModalInstanceCtrl', function ($scope, $modalInstance, config) {
$scope.config = config;
...
});
关于如何在不丢失 "set" 和 "get" 且不保留引用的情况下复制 sObj 的任何想法?
** 更新:
正如 RichS 提供的 link 所指出的,原因似乎是 getter 和 setter 属性不可枚举,因此不会被复制。这个问题是密切相关的(或者如果我们去问题的根源是重复的):Copy object with results of getters
我更新了代码:https://jsfiddle.net/vwb04d4f/3/
我手动添加了 "enumerable" 属性:
var SomeObj = function () {
var obj = {
_val: 0
}
Object.defineProperty(obj, "val", {
enumerable: true,
set : function(value) {
out("Set: " + value);
this._val = value;
},
get: function(){
return this._val;
}
});
return obj;
};
然而,扩展(从空对象)或复制都没有真正完成这项工作。也许我错过了什么?
** 更新 2 **
因为这个问题不仅仅与 angularjs 有关。
它的发生是因为 deep/shallow:
"A lazy copy is a combination of both shallow copy and deep copy. When initially copying an object, a (fast) shallow copy is used. A counter is also used to track how many objects share the data."
请阅读this or check this answer to make it more clear or even angular docs
我找到了这个问题的解决方案:What is the most efficient way to deep clone an object in JavaScript?
function cloneObject(source) {
var key,value;
var clone = Object.create(source);
for (key in source) {
if (source.hasOwnProperty(key) === true) {
value = source[key];
if (value!==null && typeof value==="object") {
clone[key] = cloneObject(value);
} else {
clone[key] = value;
}
}
}
return clone;
}
在此处查看更新后的代码:https://jsfiddle.net/vwb04d4f/6/
如您所见,"enumeration" 不是必需的。到目前为止,这段代码似乎已经解决了我的问题。感谢 Steven Vachon。
这个问题有很多答案,我测试了大部分但不是全部。
我希望能够复制一个保持 getter and setter 功能的对象。
注意:这个问题是关于 angularjs 但它也可能适用于许多其他框架。
代码位于:https://jsfiddle.net/vwb04d4f/2/
function out(str) {
document.getElementById('body').innerHTML += str + "<br>";
}
var SomeObj = function () {
var obj = {
_val: 0,
set val(value) {
out("Set: " + value);
this._val = value;
},
get val() {
return this._val;
}
}
return obj;
};
var sObj = new SomeObj();
sObj.val = 100;
var sCopy = angular.copy(sObj);
sCopy.val = 200;
out("Value:" + sCopy.val);
var sExt = angular.extend(sObj);
sExt.val = 300;
out("Value: " + sObj.val);
输出:
Set: 100
Value:200
Set: 300
Value: 300
为什么 "set val" 在 "angular.copy" 之后不再触发?如您所见,该值已正确存储。
"angular.extend" 保留引用,因此更新 sExt 将更新 sObj,这是我不想要的。
我在将范围对象传递到控制器之前复制它(模态):
$modal.open({
animation: true,
templateUrl: '/html/settings.html',
controller: 'ModalInstanceCtrl',
backdrop: false,
resolve: {
config: function() {
var cfgcpy = {};
angular.copy($scope.config, cfgcpy);
return cfgcpy;
}
}
}).result.then(function(res){
ok_func(res);
close_func();
}, function() {
close_func();
});
angular.module('app').controller('ModalInstanceCtrl', function ($scope, $modalInstance, config) {
$scope.config = config;
...
});
关于如何在不丢失 "set" 和 "get" 且不保留引用的情况下复制 sObj 的任何想法?
** 更新:
正如 RichS 提供的 link 所指出的,原因似乎是 getter 和 setter 属性不可枚举,因此不会被复制。这个问题是密切相关的(或者如果我们去问题的根源是重复的):Copy object with results of getters
我更新了代码:https://jsfiddle.net/vwb04d4f/3/
我手动添加了 "enumerable" 属性:
var SomeObj = function () {
var obj = {
_val: 0
}
Object.defineProperty(obj, "val", {
enumerable: true,
set : function(value) {
out("Set: " + value);
this._val = value;
},
get: function(){
return this._val;
}
});
return obj;
};
然而,扩展(从空对象)或复制都没有真正完成这项工作。也许我错过了什么?
** 更新 2 **
因为这个问题不仅仅与 angularjs 有关。
它的发生是因为 deep/shallow:
"A lazy copy is a combination of both shallow copy and deep copy. When initially copying an object, a (fast) shallow copy is used. A counter is also used to track how many objects share the data."
请阅读this or check this answer to make it more clear or even angular docs
我找到了这个问题的解决方案:What is the most efficient way to deep clone an object in JavaScript?
function cloneObject(source) {
var key,value;
var clone = Object.create(source);
for (key in source) {
if (source.hasOwnProperty(key) === true) {
value = source[key];
if (value!==null && typeof value==="object") {
clone[key] = cloneObject(value);
} else {
clone[key] = value;
}
}
}
return clone;
}
在此处查看更新后的代码:https://jsfiddle.net/vwb04d4f/6/
如您所见,"enumeration" 不是必需的。到目前为止,这段代码似乎已经解决了我的问题。感谢 Steven Vachon。
这个问题有很多答案,我测试了大部分但不是全部。