是否存在调用所有同名实例方法的静态方法的名称/术语?

时间:2014-07-27 23:11:59

标签: javascript oop

鉴于以下代码,是否存在静态方法的名称/术语,该方法为每个现有实例调用同名的实例方法?

这是任何编程语言的常见做法吗?

该用例能够进行一次函数调用,并确保所有实例都受到影响,而无需复制该方法的代码。

注意:这只是用于说明问题的示例代码

window.MyClass = (function(){

    var _instances = [];

    function MyClass( name ){
        _instances.push( this );
        this.name = name;
    }

    MyClass.prototype.myMethod = function( arg ) {
        console.log( this );
        console.log( arg );
    };

    // This public static method calls the instance method of the same name for each instance
    MyClass.myMethod = function(){
        var i = _instances.length;
        while( i-- ){
            var instance = _instances[i];
            instance.myMethod.apply( instance, arguments );
        }
    };

    return MyClass;

})();

a = new MyClass('a');
b = new MyClass('b');

MyClass.myMethod( true );

console.log('--------------------------------------------------------------------------------');

a.myMethod(false);
b.myMethod(false);

http://jsfiddle.net/bryandowning/7sr87/

3 个答案:

答案 0 :(得分:1)

  

...是否存在静态方法的名称/术语,该方法为每个现有实例调用同名的实例方法?

不,虽然它与pub / sub共享一些相似性。

如果您跟踪在弱地图以外的任何地方创建的每个实例(并且JavaScript没有那些 - 但[在撰写本文时参见draft ES6 spec部分§23.3.1]),您将确保这些实例可到达,因此垃圾回收无法清除它们。那不太理想。

只要可行,一个更好的方法是让所有实例都引用一个由“静态”方法更新的共享底层单例对象。他们都会通过共享引用看到更改,但是不会通过对其实例的不必要引用将它们保存在内存中。 (以下示例。)

如果在调用“静态”方法时采取操作非常重要,那么更常见的模式是让他们观察共享项目的更改,并让该项目引发改变事件。 (例如,pub / sub。)实际上,这与您的_instances数组相同(因为发布者必须知道要调用哪些订阅者),这只是一种更常见的方法。因此,在 案例中(需要采取行动),“发布/订阅”或“事件订阅者”或“汇/源”或类似内容可能是相关术语。


共享数据对象的示例:

window.MyClass = (function(){

    var shared = {};

    function MyClass( name ){
        this.name = name;
    }

    MyClass.prototype.myMethod = function() {
        console.log(this);
        console.log(shared.arg);
    };

    // This public static method calls the instance method of the same name for each instance
    MyClass.myMethod = function(arg){
        shared.arg = arg;
        console.log("set shared.arg = " + shared.arg);
    };

    return MyClass;

})();

a = new MyClass('a');
b = new MyClass('b');

MyClass.myMethod( true );

console.log('--------------------------------------------------------------------------------');

a.myMethod(false);
b.myMethod(false);

答案 1 :(得分:1)

好吧,我不确定如何命名这种模式,而我同意T.J.保持对实例的引用的克劳德是不好的做法,我想如果你有办法删除它们并不是那么糟糕,但是是的,你必须知道可能的内存泄漏。我将进一步抽象出这种模式。您可以创建一种接口,让我们称之为Instantiable并生成具有此功能的“类”,例如:

var Instantiable = function(ctor, proto) {
  var instances = []
  Object.keys(proto).forEach(function(k) {
    ctor.prototype[k] = proto[k]
  })
  ctor.prototype.new = function() {
    return instances.push(this)
  }
  ctor.prototype.delete = function() {
    return instances.splice(instances.indexOf(this), 1)
  }
  ctor.forEach = function(method) {
    var args = [].slice.call(arguments, 1)
    instances.forEach(function(instance) {
      instance[method].apply(instance, args)
    })
  }
  return ctor
}

var Person = Instantiable(
  function Person(name, age) {
    this.name = name
    this.age = age
    this.new()
  }, {
    say: function() {
      console.log(this.name, this.age)
    }
  }
)

var peter = new Person('peter', 22)
var jon = new Person('jon', 25)

Person.forEach('say')
//^ peter, 22
// jon, 25

peter.delete()

Person.forEach('say')
//^ jon, 25

答案 2 :(得分:0)

它被称为收集行为。就像一个垃圾收集器,你试图声称一些内存元素,但不像收集器,你永远不能保证删除。它漏了。垃圾收集器和其他析构函数通常都是在没有内存泄漏恐惧的情况下实现的。