在Javascript中使用.prototype的原因

时间:2009-12-22 17:48:40

标签: javascript function declaration

使用.prototype而不是在对象本身内声明函数和成员的技术原因是什么。用代码示例解释起来最容易。

使用有什么好处:

RobsObject = function(data){
    this.instanceID = data.instanceID;
    this._formButton = document.getElementById('formSubmit_' + this.instanceID);
    if(this._formButton)
    {
        //set a click listener that
        //points to this._onSubmit, this._onSuccess, and this.onFailure
    }
};

RobsObject.prototype = {
    _onSubmit: function(type, args)
    {
        //make an ajax call
    },

    _onSuccess: function(type, args)
    {
        //display data on the page
    },

    _onFailure: function(type, args)
    {
        //show an alert of some kind
    },
};

反对在Object中声明你的函数,如:

RobsObject = function(data){
    this.instanceID = data.instanceID;
    this._formButton = document.getElementById('formSubmit_' + this.instanceID);
    if(this._formButton)
    {
        //set a click listener that
        //points to this._onSubmit, this._onSuccess, and this.onFailure
    }

    this._onSubmit = function(type, args)
    {
        //make an ajax call
    }

    this._onSuccess = function(type, args)
    {
        //display data on the page
    }

    this._onFailure = function(type, args)
    {
        //show an alert of some kind
    }
};

感谢。

编辑:正如你们许多人所指出的那样,我在第二个代码段中的功能应该在它们前面加上“this”才能公开。所以我添加了它。只是我的错误。

3 个答案:

答案 0 :(得分:14)

构造函数prototype中声明的所有内容都由该构造函数的所有实例共享。如果在构造函数中定义函数,那么每个实例都会获得自己的函数副本,这会浪费内存(如果稍后比较两个实例之间的属性,可能会导致问题)。

此外,在您的示例中,构造函数中声明的函数对函数的作用域是私有的。它们不能在实例上作为成员方法调用。为此,您需要将它们分配给对象的属性:

MyObject = functon() {
  // ...

  this.myMethod = function() {
    // ...
  };
}

道格拉斯·克罗克福德(Douglas Crockford)对原型继承有很好的写作,绝对值得一试:Prototypical Inheritance in JavaScript

更新:简要原型摘要

使用构造函数创建新对象时,函数的prototype属性的值将被指定为新对象的原型对象。 (是的,这些名字令人困惑!)这就像在基于类的语言中指定一个超类一样(但不完全!阅读Crockford的页面!)

// MyObject constructor function:
MyObject = function() {
  this.a = 1;
}

// Define an object to use as a prototype.
var thePrototype = { b: 2 };

// Assign thePrototype as the prototype object for new instances of MyObject.
MyObject.prototype = thePrototype;

// Create an instance of MyObject.
var x = new MyObject();
// Everything in thePrototype is available to x.
console.log(x.b);

// x's prototype is a reference to thePrototype, so updating it affects x.
thePrototype.c = 3;
console.log(x.c);

// Setting properties on x always sets them *on x*, even if the property is
//  defined on the prototype:
x.b = 0;
y = new MyObject();
console.log(x.b);
console.log(y.b);

答案 1 :(得分:3)

答案是记忆。如果将成员放在对象本身内,那么该对象的每个实例都将包含(在内存中)所有成员。另一方面,如果您使用原型,它只存在一次,并且所有实例都将访问这些成员,就好像它们是自己的一样。

答案 2 :(得分:0)

在第一种情况下,使用new RobsObject()构造的对象具有函数_onSubmit()_onSuccess()作为其属性。它们就是所谓的对象的公共功能。

在第二种情况下,这些函数不是new RobsObject()的属性。但是,任何“公共”功能都可以看到它们(在您的情况下没有任何功能)。实际上,它们是私人功能。

但是,如果你用这种方式编写了第二个片段......

RobsObject = function(data){
    this.instanceID = data.instanceID;
    this._formButton = document.getElementById('formSubmit_' + this.instanceID);
    if(this._formButton)
    {
        //set a click listener that
        //points to this._onSubmit, this._onSuccess, and this.onFailure
    }

    this._onSubmit = function(type, args)
    {
        //make an ajax call
    }

    this._onSuccess = function(type, args)
    {
        //display data on the page
    }

    this._onFailure = function(type, args)
    {
        //show an alert of some kind
    }
};

结果是一样的。

这两个约定之间的一个重要区别是,在第一种方法中,您不能像在第二种方法中那样定义可以在许多公共函数之间共享的私有函数。用于定义原型的Object文字不像函数体那样形成闭包。

例如,

function MyConstructor() {
    var myPrivate = function() {
    }

    this.myPublic1 = function() {
        myPrivate();
    }

    this.myPublic2 = function() {
        myPrivate();
    }

}

myPrivate()是一个对两个公共函数都可见的函数。