原型或内联,有什么区别?

时间:2011-05-28 17:20:04

标签: javascript

我正在学习Javascript,我很想知道,正在使用原型声明,如下:

function TSomeObj()
{
  this.name="my object";
}

TSomeObj.prototype.showname = function() {
  alert(this.name);
}

基本上就像这样做:

function TSomeObj()
{
  this.name="my object";
  this.showname = function() {
    alert(this.name);
  }
}

当我转储对象的属性时,我得到相同的结果:

TSomeObj (inline version) =
{ 
    'name': 'my object',
    'test': function
}

TSomeObj (prototype declaration) =
{ 
    'name': 'my object',
    'test': function
}

使用原型声明的好处是什么?除了更少的混乱和更有序的源代码之外。

更新:我或许应该更清楚地表明,这是我感到好奇的最终结果。最终结果是相同的(即在对象原型中都注册了一个新函数) - 但它们的方式却截然不同。感谢您的回复和信息!

2 个答案:

答案 0 :(得分:21)

答案 1 :(得分:7)

接受的答案错过了原型和绑定到特定对象的方法之间最重要的区别,所以我要澄清

  • 原型函数只被声明一次。使用

    附加的功能
    this.method = function(){}
    
    每当您创建类的实例时,都会一次又一次地重新声明

    。因此,原型通常是将函数附加到类的首选方法,因为它们使用较少的内存,因为该类的每个实例都使用相同的函数。然而,正如Erik指出的那样,使用原型附加到附加到特定对象的函数具有不同的范围,因此原型无法访问函数构造函数中定义的“私有”变量。

  • 至于原型 实际上 是什么,因为它是来自传统OO语言的奇怪概念:

    • 每当您创建函数的新实例时:

      var obj = new Foo();
      

      运行以下逻辑(不是字面上的代码,但类似的东西):

      var inheritsFrom = Foo,
        objectInstance = {};
      
      objectInstance.__proto__ = inheritsFrom.prototype;
      
      inheritsFrom.apply( objectInstance, arguments );
      
      return objectInstance;
      

      这样:

      • 创建一个新对象{},以表示函数的新实例
      • 该函数的原型被复制到新对象的__proto__。请注意,这是一个引用副本,因此Foo.prototypeobjectInstance.__proto__现在引用 相同的 对象,并且在一个对象中进行的更改可以是立即见到了另一个。
      • 在函数
      • 中将此新对象设置为this来调用该函数
    • 并且每当您尝试访问函数或属性时,例如:obj.bar(),都会运行以下逻辑:

      if( obj.hasOwnProperty('bar') ) {
          // use obj.bar
      } else if( obj.__proto__ ){
          var proto = obj.__proto__;
          while(proto){
              if( proto.hasOwnProperty('bar') ){
                  // use proto.bar;
              }
      
              proto = proto.__proto__;
          }
      }
      

      换句话说,检查以下内容:

      obj.bar
      obj.__proto__.bar
      obj.__proto__.__proto__.bar
      obj.__proto__.__proto__.__proto__.bar
      ... etc
      

      直到__proto__最终等于null,因为您已到达原型链的末尾。

      许多浏览器现在实际公开__proto__,因此您可以在Firebug或Chrome / Safari中的控制台中进行检查。 IE没有暴露它(并且内部可能有相同的名称不同的名称)。