是否可以在原型中添加非共享变量?

时间:2016-12-14 18:02:47

标签: javascript

我正在构建一个功能,可以使用一些常用功能来改进我的一些原型。

我还想通过这个机制添加对象实例特定的变量,如:

function give_weird_container(target) {
    target.<somehow instance specific, not prototype>.underlying_container = [];
    target.prototype.container_func = function(x, y, z) {
        return this.underlying_container[x + 2*y + 3*z];
    }
}

function my_class1() {}

give_weird_container(my_class1);

现在当我创建my_class1的新实例时,它应该有一个属性&#34; uderlying_container&#34;就像我打电话那样行事一样

this.underlying_container = [];

在构造函数中。

这是否可以保留在give_weird_container函数的范围内?

2 个答案:

答案 0 :(得分:2)

  

是否可以在原型中添加非共享变量?

没有。原型上的所有属性都是共享的。只有在创建实例后才能设置的实例特定属性。

然而,你可以在原型中添加 getter ,如果它不存在,将创建一个特定于实例的属性。

例如:

Object.defineProperty(target.prototype, 'underlying_container', {
  get: function() {
    if (!this._underlying_container) {
      this._underlying_container = [];
    }
    return this._underlying_container;
  },
});

getter是共享的,但返回的值是每个实例。

如果你不喜欢每次访问this.underlying_container时执行getter的事实,你可以在第一次调用prototype属性时用实例属性替换它:

Object.defineProperty(target.prototype, 'underlying_container', {
  get: function() {
    Object.defineProperty(this, 'underlying_container', {value: []});
    return this. underlying_container;
  },
});

Object.defineProperty(this, 'underlying_container', {value: []});将在实例上创建一个具有相同名称的新属性,从而遮蔽原型上定义的getter。

要了解@ 4castle的建议,如果可以直接改变实例,那么你可以做一些这样的事情,这可能会少一些&#34;魔术&#34;:

var give_weird_container = (function() {
    function container_func(x, y, z) {
        return this.underlying_container[x + 2*y + 3*z];
    };

    return function(target) {
      target.underlying_container = [];
      target.container_func = container_func;
    };
}());

function my_class1() {}

var instance = new my_class1();

give_weird_container(instance);

答案 1 :(得分:1)

你可以给my_class1一个调用构造函数的包装函数,然后设置字段:

function give_weird_container(target) {
    target.prototype.container_func = function(x, y, z) {
        return this.underlying_container[x + 2*y + 3*z];
    }
    return function() {
        var obj = new target();
        obj.underlying_container = [];
        return obj;
    }
}

function my_class1() {}

my_class1 = give_weird_container(my_class1);