【问题标题】:Copy object with results of getters使用 getter 的结果复制对象
【发布时间】:2015-01-07 22:09:44
【问题描述】:

我有一个包含 getter 的对象。

myObject {
    id: "MyId",
    get title () { return myRepository.title; }
}

myRepository.title = "MyTitle";

我想获得这样的对象:

myResult = {
    id: "MyId", 
    title: "MyTitle"
}

我不想复制getter,所以:

myResult.title;                       // Returns "MyTitle"
myRepository.title = "Another title";
myResult.title;                       // Should still return "MyTitle"

我试过了:

  • $.extend():但它不会迭代 getter。 http://bugs.jquery.com/ticket/6145
  • 按照 here 的建议迭代属性,但不会迭代 getter。
  • 正如我所建议的here 所建议的那样,我正在使用 Angular,使用 Angular.forEach。但我只得到属性而不是吸气剂。

有什么想法吗?谢谢!

更新 我使用 Object.defineProperty 将 getter 设置为:

 "title": { get: function () { return myRepository.title; }},

可以在文档中阅读:

enumerable 当且仅当此属性在 枚举对应对象的属性。默认为 假的。

设置 enumerable: true 解决问题。

"title": { get: function () { return myRepository.title; }, enumerable: true },

【问题讨论】:

  • 抱歉,您的对象存在语法错误。您需要在 get 关键字之后删除 :function;并且您不能拥有普通的 title 属性和具有相同名称的 getter。
  • $.extend 确实工作得很好。错误描述说“jQuery.extend 复制属性 getter 返回值,而不是它们的代码。” - 但是,这正是您想要的。使用 for in 手动执行此操作也可以。
  • 对不起@Bergi,对象sintax 只是对象的console.log 的副本。我要更新问题。

标签: javascript getter-setter


【解决方案1】:

$.extend 正是你想要的。更新:你已经说过你也想要不可枚举的属性,所以它没有t 做你想做的事;请参阅下面这个答案的第二部分,但我会将第一部分留给其他人。)该错误并不是说生成的对象不会有 title 属性, 就是说生成的对象的 title 属性不会是 getter,这对于你所说的你想要的来说是完美的。

正确的 getter 语法示例:

// The myRepository object
var myRepository = { title: "MyTitle" };

// The object with a getter
var myObject = {
    id: "MyId",
    get title() { return myRepository.title; }
};

// The copy with a plain property
var copy = $.extend({}, myObject);

// View the copy (although actually, the result would look
// the same either way)
snippet.log(JSON.stringify(copy));

// Prove that the copy's `title` really is just a plain property:
snippet.log("Before: copy.title = " + copy.title);
copy.title = "foo";
snippet.log("After:  copy.title = " + copy.title);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

语法修正:

  • 添加了缺少的var=;

  • 删除重复属性title

  • 更正了 getter 声明语法


如果要包含不可枚举的属性,则需要使用 Object.getOwnPropertyNames,因为它们不会出现在 for-in 循环、Object.keys$.extend 中(无论它们是否重新“getter”或普通属性):

// The myRepository object
var myRepository = { title: "MyTitle" };

// The object with a getter
var myObject = {
    id: "MyId"
};
Object.defineProperty(myObject, "title", {
  enumerable: false, // it's the default, this is just for emphasis,
  get: function() {
    return myRepository.title;
  }
});

snippet.log("$.extend won't visit non-enumerable properties, so we only get id here:");
snippet.log(JSON.stringify($.extend({}, myObject)));

// Copy it
var copy = Object.getOwnPropertyNames(myObject).reduce(function(result, name) {
  result[name] = myObject[name];
  return result;
}, {});

// View the copy (although actually, the result would look
// the same either way)
snippet.log("Our copy operation with Object.getOwnPropertyNames does, though:");
snippet.log(JSON.stringify(copy));

// Prove that the copy's `title` really is just a plain property:
snippet.log("Before: copy.title = " + copy.title);
copy.title = "foo";
snippet.log("After:  copy.title = " + copy.title);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

【讨论】:

  • 谢谢!我已经更新了这个问题。问题是 $.extend 不适用于 getter if property.enumerable = false;
  • @MarioLevrero:没错,它们也不会像 Scimonter 那样出现在 for-in 循环中。如果您想了解不可枚举的属性,请使用Object.getownPropertyNames
  • @MarioLevrero:我已经更新了答案以展示如何使用getOwnPropertyNames(嗯,其中一种方式)。
  • 是的,感谢您的更新。我没有注意到默认情况下的 false 可枚举属性。
  • @MarioLevrero:当我第一次了解defineProperty 时,我也对此感到惊讶。
【解决方案2】:

首先,修正你的语法,虽然它在你的实际代码中可能是好的:

myObject = {
    id: "MyId",
    get title () { return myRepository.title; }
}

现在,回答。 :)

您可以使用for..in 循环来获取所有属性,然后按原样保存:

var newObj = {};
for (var i in myObject) {
    newObj[i] = myObject[i];
}

不需要 jQuery、Angular 和任何其他插件!

【讨论】:

  • 谢谢!我已经更新了这个问题。问题是 for(...) 不适用于 getter if property.enumerable = false;
猜你喜欢
  • 1970-01-01
  • 2013-06-16
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-18
  • 2021-07-29
相关资源
最近更新 更多