5

这两个使用构造函数和闭包创建的对象到底有什么不同?ab

该属性__proto__对使用闭包无法实现的任何事情有用吗?我应该在不同的情况下使用这些技术吗?内存使用有区别吗?

( jsFiddle )

window.MODULE = {};

MODULE.constructor = function(){
        this.publicVariable = 10;
};
MODULE.constructor.prototype.publicMethod = function(){
    return this.publicVariable;
};
//-------------------------------//
MODULE.closure = (function(){
    var publicMethod = function(){
        return this.publicVariable;
    };
    return function(){
        var obj = {};
        obj.publicVariable = 10;
        obj.publicMethod = publicMethod;
        return obj;
    };
}());
//-------------------------------//
var a = new MODULE.constructor();
console.log("constructor", a.publicMethod(), a)
var b = MODULE.closure();
console.log("closure", b.publicMethod(), b)

还可以看到更复杂的 jsFiddle与一些私有和静态属性的比较——据我所知,这两种技术的工作原理都是一样的......

4

3 回答 3

6

粗略地说,原型继承(你的“构造函数”方法)的主要优点是更容易做子类猴子补丁(向现有类添加方法),而如果你想要私有实例变量和方法(“受保护的方法”是仍然很难使用任何一种方法)或更喜欢词法范围而不是使用“this”的动态范围(如果有人这样做的话很有用setTimeout(obj.method, 1000)

至于性能,原型继承可能会更有效一些,因为实现是针对它进行调整的,但除非您从该类实例化大量对象,否则它实际上并不重要。


私有变量示例:

var counter  = function(){
   var count = 0; //private variable

   var increment = function(){ // private method
      count ++;
   };

   return { //public interface
      next: function(){
         increment();
         return count;
      },
   }
}

var c = counter();
console.log(c.next());
console.log(c.next());
于 2013-10-07T12:56:12.040 回答
1

如果我们跳过 OOP 方法的优点,当从它的原型继承这个方法时,a和之间的区别bb有自己的方法:publicMethoda

a.hasOwnProperty('publicMethod'); // false
b.hasOwnProperty('publicMethod'); // true

请注意,该__proto__属性是非标准的,在 IE < 11 中不受支持。或者,您可以使用 ES5 功能Object.getPrototypeOf(a)

另请注意 JavaScript 1的命名约定:

  • UPPER_CASE用于常量,当全局变量通常使用时PascalCase,你MODULE应该是Module
  • 构造函数PascaleCase也使用,所以你MODULE.constructor应该是Module.Constructor.
于 2013-10-07T13:15:14.173 回答
0

更多关于原型、继承、覆盖和调用 super 的信息:https ://stackoverflow.com/a/16063711/1641941

MODULE={};
MODULE.constructor = function(){
  this.publicVariable = 10;
};
MODULE.constructor.prototype=(function(){
  var privateMethod=function(){
   console.log("I'm private");
  };
  return {
    publicMethod : function(){
      //going to call "private" method
      privateMethod();
      return this.publicVariable;
    }
  };
}());
var c = new MODULE.constructor();
c.publicMethod();

要拥有特定于实例的“私有”成员值,您必须放弃原型,因为您必须在构造函数体而不是原型上定义访问这些值的所有函数。我个人认为强行实现 JavaScript 不支持的东西(私有实例特定变量)并放弃 JavaScript 支持的东西(原型)是愚蠢的。

支持我的意思是 JS 引擎会为它优化你的代码。

于 2013-10-07T15:49:15.183 回答