2010-09-23 10 views
111

Soy relativamente nuevo en JavaScript y sigo viendo .extend y .prototype en bibliotecas de terceros que estoy usando. Pensé que tenía que ver con la biblioteca de JavaScript Prototype, pero estoy empezando a pensar que ese no es el caso. ¿Para qué se usan?JavaScript: ¿Para qué se utilizan .extend y .prototype?

Respuesta

119

La herencia de Javascript se basa en prototipos, por lo que amplía los prototipos de objetos como Fecha, Matemáticas e incluso los propios.

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

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

En el fragmento anterior, que definen un método para todos los objetos Date (los ya existentes y todos los nuevos).

extend suele ser una función de alto nivel que copia el prototipo de una nueva subclase que desea extender desde la clase base.

Así que usted puede hacer algo como:

extend(Fighter, Human) 

Y el Fighter constructor/objeto heredará el prototipo de Human, por lo que si se define métodos tales como live y die en Human continuación Fighter también heredará esos.

Aclaración Actualizado:

"función de alto nivel", que significa .extend no está incorporado, pero a menudo proporciona una biblioteca como jQuery o Prototype.

+69

"función de alto nivel", que significa '.extend' no está incorporado, pero a menudo proporcionada por dicha biblioteca como jQuery o Prototype. – visum

+13

Me gustaría añadir que no se sugiere extender los prototipos de objetos nativos en JS – framp

+1

@meder; debe agregar el comentario de visum en su respuesta. :) –

22

.extend() es agregado por muchas bibliotecas de terceros para facilitar la creación de objetos desde otros objetos. Ver http://api.jquery.com/jQuery.extend/ o http://www.prototypejs.org/api/object/extend para algunos ejemplos.

.prototype se refiere a la "plantilla" (si desea llamarlo así) de un objeto, por lo que al agregar métodos al prototipo de un objeto (esto se ve mucho en bibliotecas para agregar a Cadena, Fecha, Matemáticas o Even Function) esos métodos se agregan a cada nueva instancia de ese objeto.

18

El método extend por ejemplo en jQuery o PrototypeJS, copia todas las propiedades del origen al objeto de destino.

Ahora sobre la propiedad prototype, es un miembro de los objetos de función, es parte del núcleo del lenguaje.

Cualquier función se puede utilizar como constructor, para crear nuevas instancias de objetos. Todas las funciones tienen esta propiedad prototype.

Cuando utiliza el operador new con un objeto de función, se creará un nuevo objeto y heredará de su constructor prototype.

Por ejemplo:

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

var foo = new Foo(); 

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

Javascript herencia parece ser como un debate abierto en todas partes. Se puede llamar "El curioso caso del lenguaje Javascript".

La idea es que hay una clase base y luego extiende la clase base para obtener una característica similar a la herencia (no completamente, pero aún).

La idea es obtener lo que el prototipo realmente significa. No lo obtuve hasta que vi el código de John Resig (cerca de lo que jQuery.extend) escribió un fragmento de código que lo hace y afirma que las bibliotecas base2 y prototipo fueron la fuente de inspiración.

Aquí está el código.

/* 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; 
    }; 
})(); 

Hay tres partes que están haciendo el trabajo. Primero, recorre las propiedades y las agrega a la instancia. Después de eso, se crea un constructor para posteriormente ser añadido a la object.Now, las líneas principales son:

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

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

Usted primer punto del Class.prototype al prototipo deseado. Ahora, todo el objeto ha cambiado, lo que significa que necesita forzar el diseño a su propio diseño.

Y el ejemplo de uso:

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

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

leer mas sobre esto aquí en Javascript Inheritance by John Resig 's puesto.

1

Algunas funciones de extend en bibliotecas de terceros son más complejas que otras. Knockout.js, por ejemplo, contiene un mínimo sencillo que no tiene algunos de los cheques que jQuery es lo hace:

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