JavaScript:.extend和.prototype分别用于什么?


122

我对JavaScript比较陌生,并且在正在使用的第三方库中不断看到.extend和.prototype。我以为它与Prototype javascript库有关,但我开始认为并非如此。这些是做什么用的?

Answers:


136

Javascript的继承是基于原型的,因此您可以扩展对象的原型,例如Date,Math,甚至是您自己的自定义对象。

Date.prototype.lol = function() {
 alert('hi');
};

( new Date ).lol() // alert message

在上面的代码段中,我为所有 Date对象(现有对象和所有新对象)定义了一个方法。

extend 通常是一个高级函数,用于复制要从基类扩展的新子类的原型。

因此,您可以执行以下操作:

extend( Fighter, Human )

并且Fighter构造函数/对象将继承的原型Human,因此,如果您定义诸如liveand dieon之类的方法,HumanFighter也将继承这些方法。

更新的说明:

“高级功能”的意思是.extend不是内置的,但通常由jQuery或Prototype之类的库提供。


75
“高级功能”的含义.extend不是内置的,而是通常由jQuery或Prototype之类的库提供。
visum

13
我要补充一点,不建议在JS中扩展本机对象的原型
framp

1
@meder-您应该在答案中添加visum评论。:)
Manish Gupta'5

9
在现代Javascript编程中,习惯将全局变量和本机对象视为公共浴室的元素。您无法避免进入该处,但应尽量减少与表面的接触。这是因为changing the native objects can break other developer's assumptions of these objects,导致javascript错误,通常可能需要花费数小时才能进行跟踪。此答案的开头一句话似乎歪曲了这种有价值的javascript做法。
Ninjaxor

24

.extend()许多第三方库都添加了,从而可以轻松地从其他对象创建对象。有关某些示例,请参见http://api.jquery.com/jQuery.extend/http://www.prototypejs.org/api/object/extend

.prototype 指对象的“模板”(如果要调用它的话),因此通过将方法添加到对象的原型中(在库中可以看到很多,可以添加到String,Date,Math甚至Function中),这些方法被添加到该对象的每个新实例。


19

extend,例如在方法的jQueryPrototypeJS,复制所有从源到目的对象的属性。

现在关于prototype属性,它是函数对象的成员,是语言核心的一部分。

任何函数都可以用作构造函数,以创建新的对象实例。所有功能都具有此prototype属性。

new功能对象上使用运算符时,将创建一个新对象,该对象将从其构造函数继承prototype

例如:

function Foo () {
}
Foo.prototype.bar = true;

var foo = new Foo();

foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true

18

Javascript继承似乎到处都是公开辩论。可以将其称为“ Java语言的奇特案例”。

这个想法是有一个基类,然后您扩展该基类以获得类似继承的功能(不完全,但仍然)。

整个想法是获得原型的真正含义。直到我看到John Resig的代码(接近所做的事情jQuery.extend),我才得到它,并且他声称base2和原型库是灵感的源泉。

这是代码。

    /* Simple JavaScript Inheritance
     * By John Resig http://ejohn.org/
     * MIT Licensed.
     */  
     // Inspired by base2 and Prototype
    (function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);        
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.prototype.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();

工作分为三个部分。首先,您遍历属性并将其添加到实例。之后,创建一个构造函数供以后添加到对象中,现在关键行是:

// Populate our constructed prototype object
Class.prototype = prototype;

// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;

您首先将指向Class.prototype所需的原型。现在,整个对象已更改,这意味着您需要将布局强制回到其自己的布局。

以及用法示例:

var Car = Class.Extend({
  setColor: function(clr){
    color = clr;
  }
});

var volvo = Car.Extend({
   getColor: function () {
      return color;
   }
});

John Resig的文章《Javascript继承》中阅读有关此内容的更多信息。


2

extend第三方库中的某些功能比其他功能更复杂。例如,Knockout.js包含一个最简单的示例,其中没有jQuery的某些检查:

function extend(target, source) {
    if (source) {
        for(var prop in source) {
            if(source.hasOwnProperty(prop)) {
                target[prop] = source[prop];
            }
        }
    }
    return target;
}

2
  • .extends() 创建一个班级,该班级是另一个班级的子级。
    幕后 Child.prototype.__proto__将其值设置为,Parent.prototype
    以便继承方法。
  • .prototype 彼此继承特征。
  • .__proto__ 是原型的获取者/设置者。

应该不是.extend()而不是 .extends()吗?
SJHowe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.