【问题标题】:Attaching methods to prototype from within constructor function从构造函数中将方法附加到原型
【发布时间】:2010-03-11 22:10:53
【问题描述】:

这是在 JavaScript 中描述“类”或构造函数的教科书标准方法,直接来自 JavaScript 权威指南

function Rectangle(w,h) {
    this.width = w;
    this.height = h;
}
Rectangle.prototype.area = function() { 
    return this.width * this.height;
};

我不喜欢这里的悬空原型操作,所以我试图想办法将area 的函数定义封装在构造函数中。我想出了这个,我确实期望它会起作用:

function Rectangle(w,h) {
    this.width = w;
    this.height = h;
    this.constructor.prototype.area = function() { 
        return this.width * this.height;
    };
}

我没想到这会起作用,因为 area 函数内的 this 引用应该指向 area 函数本身,所以我无法访问 widthheight this。但事实证明我愿意!

var rect = new Rectangle(2,3);
var area = rect.area(); // great scott! it is 6

一些进一步的测试证实,area 函数中的 this 引用实际上是对 正在构建的对象的引用,而不是 area 函数本身。

function Rectangle(w,h) {
    this.width = w;
    this.height = h;
    var me = this;
    this.constructor.prototype.whatever = function() { 
        if (this === me) { alert ('this is not what you think');}
    };
}

原来警报弹出,this 正是正在构建的对象。那么这里发生了什么?为什么this 不是我期望的this

【问题讨论】:

  • 如果您有一百个矩形,您将重新声明该原型方法一百次。还好你只有一种方法……

标签: javascript prototypal-inheritance


【解决方案1】:

我认为正确的答案是你不应该这样做,因为正如肯尼贝克在评论中所说:

如果你有一百个矩形,你 将重新声明该原型 方法一百次。

【讨论】:

    【解决方案2】:

    我认为“this”总是指调用函数所针对的对象。

    【讨论】:

    • 我认为官方的回答是“视情况而定”。
    • 为了澄清,this 指的是当函数用作对象上的方法时调用函数的对象。这不是这里的情况。在这种情况下,函数作为函数而不是对象上的方法被调用,因此this 确实应该引用全局对象。
    【解决方案3】:

    this 的含义取决于函数的调用方式:

    • this 通常是指在运行时调用函数的对象,例如当被称为ob.foo() 时,foo 中的this 将引用ob。
    • 如果以不提供对象的方式调用函数,例如只是foo()this 指的是全局变量(在你的 js 程序中包含所有其他全局变量的顶层对象)。
    • 而在.call().apply() 中,提供了this 所指的对象。

    现在,如果您想要一种方法来指向创建您的函数的函数的对象(即创建时的第二级 this),那么您将不得不重命名更深的 @987654332 @ 让它通过当前可见的发光。如果这很清楚,这应该有助于澄清一点:

    function outside() {
        // Here, 'this' refers to the object outside() is called with.
        // Let's "rename" this, to make it visible to inside functions.
        var that = this,
            private = 42;
    
        return {
            inside: function {
                // here, 'this' refers to the object inside() is called with,
                //  it is hiding outside's this.
                // Also, 'that' refers to the object outside() was called with,
                //  *at the time* outside was called and inside was created.
                // Notice that you can see 'private'
                // (but nobody outside of 'outside()) can!
                return private;
            }
        }
    }
    

    上面的这种模式对于使用可以访问私有成员的公共方法创建对象很有用。请参阅Crockford 以获得更好的解释。

    【讨论】:

      【解决方案4】:

      'this' 指向什么,在代码运行时确定。

      这是找出“this”应该是什么的简单方法。

      如果你使用'.'要引用函数,“this”将引用“。”左侧的任何内容。

      (这不包括 .call 和 .apply)

      var myFn = function () {
      return this.name + ' called me';
      };
      
      var me = {
      name : 'oatkiller',
      shoutOut : myFn
      };
      
      var you = {
      name : 'Matthew',
      shoutOut : myFn
      };
      
      // im on the left of the dot, so this points to me
      me.shoutOut(); // 'oatkiller called me'
      
      // youre on the left of the dot, so this points to you
      you.shoutOut(); // 'Matthew called me'
      

      【讨论】:

        【解决方案5】:

        我认为您与最后一个示例非常接近。使用特权方法怎么样:

        function Rectangle(w,h) {
          this.width = w;
          this.height = h;
          var that = this;
          this.area = function() { 
            return that.width * that.height;
          }
        }
        
        var rect = new Rectangle(2,3);
        console.log(rect.area());
        

        请参阅Crockford's "Private Members in JavaScript" 了解更多信息。

        【讨论】:

          猜你喜欢
          • 2015-10-16
          • 2015-10-10
          • 2011-10-30
          • 2013-03-22
          • 1970-01-01
          • 1970-01-01
          • 2011-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多