骨干:原型对象的烦人行为 [英] Backbone: annoying behaviour of prototype object

查看:76
本文介绍了骨干:原型对象的烦人行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这是JavaScript本身的问题(或行为),而不是Backbone的extend方法,但是我想知道避免这种情况的最佳策略是什么.

I understand this is a problem (or behaviour) of javascript itself rather than Backbone's extend method, but I'd like to know what is the best strategy to avoid it.

最好将其放在代码中:

var MyModel = Backbone.Model.extend({
  value: 0,
  values: []
});

var myFirstModel = new MyModel();

myFirstModel.value // 0, as expected
myFirstModel.values // [], as expected

var mySecondModel = new MyModel();

mySecondModel.value = 2;
mySecondModel.values.push(2)

mySecondModel.value // 2, as expected
mySecondModel.values // [2], as expected

myFirstModel.value // 0, as expected
myFirstModel.values // [2], ... WAT!!!

我确实知道问题是我没有为mySecondModel.values分配新值,我只是对原型中的values变量即MyModel.prototype.values进行操作(与其他问题相同)对象,当然)

I do understand that the problem is I'm not assigning a new value to mySecondModel.values I'm just operating on the values variable that is in the prototype, that is MyModel.prototype.values (same problem with any other object, of course)

但是很容易将其弄乱.最直观的事情就是将其视为INSTANCE变量,而不是每个实例通用的变量(基于类的语言中的静态或类变量).

But it's very easy to mess with that. The most intuitive thing is to just think of those as INSTANCE variables, and not variables common to every instance (static or class variables in class based languages).

到目前为止,我发现的一般解决方案是初始化initialize方法中的每个变量,如下所示:

So far now the general solution I've found is to initialize every variable in the initialize method, like this:

var MyModel = Backbone.Model.extend({
  initialize: function() {
    this.value = 0;
    this.values = [];
  }
});

这样,一切都会按预期进行,即使对于一个简单的值(例如this.value)来说并不是必需的,我发现在每种情况下坚持这一原则都容易得多.

That way everything works as expected, and even though it wouldn't be neccesary for a simple value (like this.value) I find it much easier to just stick to this prnciple in every case.

我想知道是否有更好(更优雅,更清晰)的解决方案

I'm wondering if there's some better (more elegant, clearer) solution to this problem

推荐答案

这是JavaScript原型继承的结果,并且Array对象是引用类型.您传递给extend的对象的键/值对被复制到MyModel的原型上,因此它们将由MyModel的所有实例共享.由于values是一个数组,因此在修改它时,将为每个实例修改该数组.

This is an effect of JavaScript's prototypical inheritance and the fact that Array objects are reference types. The key/value pairs of the object you pass to extend are copied onto the prototype of MyModel, so they will be shared by all instances of MyModel. Because values is an array, when you modify it, you modify the array for every instance.

通过在initialize中设置values进行的操作称为对原型进行阴影处理,这是解决此问题的正确方法.

What you are doing by setting values inside initialize is called shadowing the prototype, and it is the correct way to solve this issue.

也就是说,在Backbone.Model的情况下,如果尝试处理模型的属性,则可以使用defaults函数提供如下默认值:

That said, in the case of Backbone.Model, if you are attempting to deal with the model's attributes, you can use the defaults function to provide defaults like this:

var MyModel = Backbone.Model.extend({
  defaults: function() {
    return {
      value: 0,
      values: []
    }
  }
});

同样,这仅适用于实例的属性.

Again, this is only for attributes of an instance.

var inst = new MyModel();

// The defaults will be created for each new model,
// so this will always return a new array.
var values = inst.get('values');

对于您正在做的事情,您要在模型本身上指定属性,如您所愿,您可以在initialize内部设置默认值.

For what you are doing, where you are specifying properties on the model itself, it is up to you to set the defaults inside of initialize, as you have done.

这篇关于骨干:原型对象的烦人行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆