admin管理员组文章数量:1410682
I have an object that contains a getter.
myObject {
id: "MyId",
get title () { return myRepository.title; }
}
myRepository.title = "MyTitle";
I want to obtain an object like:
myResult = {
id: "MyId",
title: "MyTitle"
}
I don't want to copy the getter, so:
myResult.title; // Returns "MyTitle"
myRepository.title = "Another title";
myResult.title; // Should still return "MyTitle"
I've try:
- $.extend(): But it doesn't iterate over getters.
- Iterating properties as suggested here, but it doesn't iterate over getters.
- As I'm using angular, using Angular.forEach, as suggested here. But I only get properties and not getters.
Any idea? Thx!
Update I was setting the getter using Object.defineProperty as:
"title": { get: function () { return myRepository.title; }},
As can be read in the doc:
enumerable true if and only if this property shows up during enumeration of the properties on the corresponding object. Defaults to false.
Setting enumerable: true fix the problem.
"title": { get: function () { return myRepository.title; }, enumerable: true },
I have an object that contains a getter.
myObject {
id: "MyId",
get title () { return myRepository.title; }
}
myRepository.title = "MyTitle";
I want to obtain an object like:
myResult = {
id: "MyId",
title: "MyTitle"
}
I don't want to copy the getter, so:
myResult.title; // Returns "MyTitle"
myRepository.title = "Another title";
myResult.title; // Should still return "MyTitle"
I've try:
- $.extend(): But it doesn't iterate over getters. http://bugs.jquery./ticket/6145
- Iterating properties as suggested here, but it doesn't iterate over getters.
- As I'm using angular, using Angular.forEach, as suggested here. But I only get properties and not getters.
Any idea? Thx!
Update I was setting the getter using Object.defineProperty as:
"title": { get: function () { return myRepository.title; }},
As can be read in the doc:
enumerable true if and only if this property shows up during enumeration of the properties on the corresponding object. Defaults to false.
Setting enumerable: true fix the problem.
"title": { get: function () { return myRepository.title; }, enumerable: true },
Share
Improve this question
edited May 23, 2017 at 12:15
CommunityBot
11 silver badge
asked Nov 11, 2014 at 11:13
Mario LevreroMario Levrero
3,3774 gold badges27 silver badges59 bronze badges
3
-
3
Sorry, but your object is a syntax error. You need to remove
:function
after aget
keyword; and you cannot have a normaltitle
property and a getter with the same name. – Bergi Commented Nov 11, 2014 at 11:19 -
2
$.extend
does work very well. The bug description says "jQuery.extend copies property getter return values, not their code." - however, that's just what you want. Doing it manually withfor in
will do the same. – Bergi Commented Nov 11, 2014 at 11:21 - Sorry @Bergi, the object sintax is just a copy of the console.log for the object. I'm going to update the question. – Mario Levrero Commented Nov 11, 2014 at 11:23
3 Answers
Reset to default 4 (Update: You've since said you want non-enumerable properties as well, so it doesn't do what you want; see the second part of this answer below, but I'll leave the first bit for others.) The bug isn't saying that the resulting object won't have a $.extend
does exactly what you want.title
property, it's saying that the resulting object's title
property won't be a getter, which is perfect for what you said you wanted.
Example with correct getter syntax:
// The myRepository object
const myRepository = { title: "MyTitle" };
// The object with a getter
const myObject = {
id: "MyId",
get title() { return myRepository.title; }
};
// The copy with a plain property
const copy = $.extend({}, myObject);
// View the copy (although actually, the result would look
// the same either way)
console.log(JSON.stringify(copy));
// Prove that the copy's `title` really is just a plain property:
console.log("Before: copy.title = " + copy.title);
copy.title = "foo";
console.log("After: copy.title = " + copy.title);
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Syntax fixes:
Added missing variable declarations,
=
, and;
Removed duplicate property
title
Corrected the getter declaration syntax
If you want to include non-enumerable properties, you'll need to use Object.getOwnPropertyNames
because they won't show up in a for-in
loop, Object.keys
, or $.extend
(whether or not they're "getter" or normal properties):
// The myRepository object
const myRepository = { title: "MyTitle" };
// The object with a getter
const myObject = {
id: "MyId",
};
Object.defineProperty(myObject, "title", {
enumerable: false, // it's the default, this is just for emphasis,
get: function () {
return myRepository.title;
},
});
console.log("$.extend won't visit non-enumerable properties, so we only get id here:");
console.log(JSON.stringify($.extend({}, myObject)));
// Copy it
const copy = {};
for (const name of Object.getOwnPropertyNames(myObject)) {
copy[name] = myObject[name];
}
// View the copy (although actually, the result would look
// the same either way)
console.log("Our copy operation with Object.getOwnPropertyNames does, though:");
console.log(JSON.stringify(copy));
// Prove that the copy's `title` really is just a plain property:
console.log("Before: copy.title = " + copy.title);
copy.title = "foo";
console.log("After: copy.title = " + copy.title);
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
First of all, fix your syntax, though it probably is good in your actual code:
myObject = {
id: "MyId",
get title () { return myRepository.title; }
}
Now, to the answer. :)
You can just use a for..in
loop to get all the properties, then save them as-is:
var newObj = {};
for (var i in myObject) {
newObj[i] = myObject[i];
}
No jQuery, Angular, any other plugins needed!
I had the same issue but in TypeScript and the method mentioned by T.J. Crowder didnt work.
What did work was the following:
TypeScript:
function copyObjectIncludingGettersResult(originalObj: any) {
//get the properties
let copyObj = Object.getOwnPropertyNames(originalObj).reduce(function (result: any, name: any) {
result[name] = (originalObj as any)[name];
return result;
}, {});
//get the getters values
let prototype = Object.getPrototypeOf(originalObj);
copyObj = Object.getOwnPropertyNames(prototype).reduce(function (result: any, name: any) {
//ignore functions which are not getters
let descriptor = Object.getOwnPropertyDescriptor(prototype, name);
if (descriptor?.writable == null) {
result[name] = (originalObj as any)[name];
}
return result;
}, copyObj);
return copyObj;
}
Javascript version:
function copyObjectIncludingGettersResult(originalObj) {
//get the properties
let copyObj = Object.getOwnPropertyNames(originalObj).reduce(function (result, name) {
result[name] = originalObj[name];
return result;
}, {});
//get the getters values
let prototype = Object.getPrototypeOf(originalObj);
copyObj = Object.getOwnPropertyNames(prototype).reduce(function (result,name) {
let descriptor = Object.getOwnPropertyDescriptor(prototype, name);
if (descriptor?.writable == null) {
result[name] = originalObj[name];
}
return result;
}, copyObj);
return copyObj;
}
本文标签: javascriptCopy object with results of gettersStack Overflow
版权声明:本文标题:javascript - Copy object with results of getters - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745019885a2638066.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论