-
Notifications
You must be signed in to change notification settings - Fork 27.4k
angular.copy not copying accessors (getters/setters) #5085
Comments
There are a number of issues related to I guess we either need to make it much more powerful or state that it is really only supposed to be used for simple copies of plain objects and expect developers to use a 3rd party copy library or write their own if they want this kind of stuff. @IgorMinar, @mhevery and @vojtajina - what do you think? |
As reported in #5063, Concerning this issue, unfortunately it does not seem to have standard solution to copy setters and getters. |
It seems that if you specify the property as |
Using |
I think you are right. It looks like the solution is to copy all the properties as well as their descriptors, using for example a |
Just some food for thought: To my knowledge, it is impossible to create an exact copy of arbitrary objects in Javascript. (Edit: wording) Copying getters and setters does not resolve this goal, and complicates the issue for users that expect an exact copy. Consider:
Now let's create an instance and copy it:
The objects still share state. (Yes, it is a very simple example.) Other programming languages have tackled that problem: They delegate to the object via a copy-method. Domain-objects can decide how to a copy of themselves should be created. These languages have standardized this, though. |
Is there anything in ES2015-2016 with regards to delegating to a copy-method? I know there are proxies and annotations, but I do not know if they allow this kind of behavior directly. Maybe you could make an annotation or proxy (or an annotation on a proxy object) that makes the getter(s) delegate to another function on copy, or something similar. |
My use case may have been different than the issue author's (I don't recall). I wanted to copy both the property definitions and the state. I'm don't know about a Modifying @timostamm's example:
|
Object.assign requires the properties to be enumerable, which a 3rd party library might not do. It is also unable to recreate constructor-arguments, which means it cannot copy Foo if it was constructed with a custom initial value. Slightly modified example:
new Foo(999) cannot be cloned using Object.assign without knowledge about the implementation of Foo. Other examples:
These examples may seem far-fetched, but they will happen sometime, somewhere, which is why angular cannot provide a catch-all copy function. I see two approaches to make it generic: a) make it possible to override the copy-functionI am not sure how this would work. If one piece of software requires a specific implementation and another piece of software requires a different implementation, how would you merge the functionality? b) honor a magic $$copy methodThis is a proven concept and should work out without noticable performance degradation. Foo would have to implement:
And possibly:
|
@timostamm: You bring up good points. There are indeed several 'copy' scenarios that the |
A very dirty hack works on 1.5 / 1.6: const copiableProperties = function (object, details) {
Object.defineProperties(object, details);
object.cloneNode = (function (cloneNode) {
return function () {
const that = angular.copy(Object.assign({}, this, { cloneNode }));
Object.defineProperties(that, details);
that.cloneNode = angular.copy(this.cloneNode);
return that;
};
}(object.cloneNode));
}; |
Closes angular#5085 Closes angular#13193 Closes angular#14352 Closes angular#15904 Closes angular#16055 Closes angular#16061 Closes angular#16067
Closes angular#5085 Closes angular#13193 Closes angular#14352 Closes angular#15904 Closes angular#16055 Closes angular#16061 Closes angular#16067
Closes angular#5085 Closes angular#13193 Closes angular#14352 Closes angular#15904 Closes angular#16055 Closes angular#16061 Closes angular#16067
Closes angular#5085 Closes angular#13193 Closes angular#14352 Closes angular#15904 Closes angular#16055 Closes angular#16061 Closes angular#16067
It seems like angular.copy doesn't re-create accessors (getter/setter properties) when cloning, which leads to a break in behavior.
For instance:
The text was updated successfully, but these errors were encountered: