通过实例方法

时间:2015-05-24 23:47:24

标签: javascript prototype

在JavaScript中,是否可以在影响其所有兄弟姐妹的对象上调用实例方法?

例如,假设我有以下课程:



function Thing() {
  this.active = false;
}

Thing.prototype = {
  constructor: Thing,

  activate: function() {
    this.active = true;
  },
  deactivate: function() {
    this.active = false;
  }
  
};




我是否可以创建一个可以激活类activateAll的所有实例的Thing方法?

我需要this.active成为实例变量。

2 个答案:

答案 0 :(得分:7)

您可以将所有实例存储在数组中,并迭代它们以更改其active属性。但是,存储所有实例意味着它们不会被垃圾回收,因此您将浪费内存。如果阵列变得庞大,那么迭代就会很慢。

var Thing = (function() { // Use a closure to hide `instances`
  var instances = [];
  function Thing() {
    this.active = false;
    instances.push(this);
  }
  Thing.prototype.activate = function() {
    this.active = true;
  };
  Thing.prototype.activateAll = function() {
    instances.forEach(function(instance) {
      instance.active = true;
    });
  };
  return Thing;
})();

更好的方法是为每个实例定义公共默认活动和默认优先级,以及自己的活动和自己的优先级。然后,

  • 要获取实例的活动,请比较默认优先级和自己的优先级。最大的决定是应该返回默认活动还是自己的活动。
  • 要设置实例的活动,请更新自己的活动。如果默认活动较大,请增加自己的优先级。
  • 要设置所有实例的活动,请更新默认活动并增加默认优先级。
var Thing = (function() {
    var defActive = false, /* default activity */
        defPriority = 0; /* default priority */
    /* `defPriority >= ownPriority` will always hold */
    function Thing() {
        var ownActive,
            ownPriority = -1;
        Object.defineProperty(this, 'active', {
            get: function() {
                return defPriority > ownPriority ? defActive : ownActive;
            },
            set: function(val) {
                ownActive = val;
                ownPriority = defPriority;
            }
        });
    }
    Thing.prototype.activate = function() {
        this.active = true;
    };
    Thing.prototype.activateAll = function() {
        defActive = true;
        ++defPriority;
    };
    return Thing;
})();

如果多次调用activateAll并且您不想不必要地增加defPriority,则可以添加一个布尔变量来了解某些属性是否达到默认属性。

var Thing = (function() {
  var defActive = false, /* default activity */
      defPriority = 0, /* default priority */
      someOwnPriorityReachedDefPriority = false;
  function Thing() {
    var ownActive,
        ownPriority = -1;
    Object.defineProperty(this, 'active', {
      get: function() {
        return defPriority > ownPriority ? defActive : ownActive;
      },
      set: function(val) {
        ownActive = val;
        ownPriority = defPriority;
        someOwnPriorityReachedDefPriority = true;
      }
    });
  }
  Thing.prototype.activate = function() {
    this.active = true;
  };
  Thing.prototype.activateAll = function() {
    defActive = true;
    if(someOwnPriorityReachedDefPriority) {
      ++defPriority;
      someOwnPriorityReachedDefPriority = false;
    }
  };
  return Thing;
})();

在任何情况下,请注意在原型中添加该方法没有多大意义。根据OOP原则,在变量中调用方法不应影响其他变量。相反,请考虑将该方法添加到构造函数本身。

一个完整的例子可能是这样的:

var Thing = (function() {
  var defActive = false, /* default activity */
      defPriority = 0, /* default priority */
      someOwnPriorityReachedDefPriority = false;
  function Thing() {
    var ownActive,
        ownPriority = -1;
    Object.defineProperty(this, 'active', {
      get: function() {
        return defPriority > ownPriority ? defActive : ownActive;
      },
      set: function(val) {
        ownActive = val;
        ownPriority = defPriority;
        someOwnPriorityReachedDefPriority = true;
      }
    });
  }
  Thing.prototype.activate = function() {
    this.active = true;
  };
  Thing.prototype.deactivate = function() {
    this.active = false;
  };
  Object.defineProperty(Thing, 'activeAll', {
    set: function(val) {
      defActive = val;
      if(someOwnPriorityReachedDefPriority) {
        ++defPriority;
        someOwnPriorityReachedDefPriority = false;
      }
    }
  });
  Thing.activateAll = function() {
    Thing.activeAll = true;
  };
  Thing.deactivateAll = function() {
    Thing.activeAll = false;
  };
  return Thing;
})();

答案 1 :(得分:1)

你需要一个instances数组,如下所示:

var instances = [];

修改Thing,如下所示:

function Thing() {
  this.active = false;
  instances[instances.length] = this;
}

通过迭代实现方法:

function activateAll() {
    for (var index in instances) {
        instances[index].active = true;
    }
}

您可以概括一下,如下所示:

function genericOperation(f, p) {
    for (var index in instances) {
        instances[index].f(p);
    }
}