JavaScript: .extend ve .prototype ne için kullanılır?


122

JavaScript konusunda nispeten yeniyim ve kullandığım üçüncü taraf kitaplıklarında .extend ve .prototype görmeye devam ediyorum. Prototype javascript kitaplığıyla ilgili olduğunu düşünmüştüm, ancak durumun bu olmadığını düşünmeye başlıyorum. Bunlar ne için kullanılıyor?

Yanıtlar:


136

Javascript'in kalıtımı prototip tabanlıdır, bu nedenle Tarih, Matematik gibi nesnelerin prototiplerini ve hatta kendi özel olanlarınızı genişletirsiniz.

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

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

Yukarıdaki kod parçacığında, tüm Date nesneleri (zaten mevcut olanlar ve tüm yenileri) için bir yöntem tanımlıyorum .

extend genellikle temel sınıftan genişletmek istediğiniz yeni bir alt sınıfın prototipini kopyalayan yüksek düzeyli bir işlevdir.

Böylece şöyle bir şey yapabilirsiniz:

extend( Fighter, Human )

Ve Fighteryapıcı / nesne prototipini miras alır Human, bu nedenle liveve dieon gibi yöntemleri tanımlarsanız , Humano Fighterzaman bunları da miras alır.

Güncellenen Açıklama:

"yüksek seviyeli işlev" anlamına gelen .extend yerleşik değildir, ancak genellikle jQuery veya Prototype gibi bir kitaplık tarafından sağlanır.


75
"yüksek seviyeli işlev" anlamı .extendyerleşik değildir, ancak genellikle jQuery veya Prototype gibi bir kitaplık tarafından sağlanır.
visum

13
JS'de yerel nesnelerin prototiplerini genişletmenin önerilmediğini ekleyeceğim
framp

1
@meder - cevabınıza visum yorumu eklemelisiniz. :)
Manish Gupta

9
Modern Javascript programlamasında, genel ve yerel nesnelere umumi bir banyonun öğeleri gibi davranmak gelenekseldir; oraya girmekten kaçınamazsınız, ancak yüzeylerle teması en aza indirmeye çalışmalısınız. Bunun nedeni changing the native objects can break other developer's assumptions of these objects,, izlenmesi genellikle saatler süren javascript hatalarının ortaya çıkmasıdır. Bu cevabın başındaki cümle, bu değerli javascript uygulamasını yanlış temsil ediyor gibi görünüyor.
Ninjaxor

24

.extend()diğer nesnelerden nesne oluşturmayı kolaylaştırmak için birçok üçüncü taraf kitaplığı tarafından eklenir. Bazı örnekler için http://api.jquery.com/jQuery.extend/ veya http://www.prototypejs.org/api/object/extend adresine bakın .

.prototype bir nesnenin "şablonunu" (onu çağırmak istiyorsanız) ifade eder, bu nedenle bir nesnenin prototipine yöntemler ekleyerek (bunu kitaplıklarda String, Date, Math ve hatta Function'a eklemek için çok görürsünüz) bu yöntemler o nesnenin her yeni örneğine eklenir.


19

extendÖrneğin bir yöntem jQuery veya PrototypeJS , hedef nesnenin kaynaktan kopyaları özellikleri.

Şimdi hakkında prototype özellik işlev nesnelerinin bir üyesidir, dil çekirdeğinin bir parçasıdır.

Yeni nesne örnekleri oluşturmak için herhangi bir işlev kurucu olarak kullanılabilir . Tüm işlevler buna sahiptirprototype özelliğe sahiptir.

newİşleci bir işlev nesnesi üzerinde kullandığınızda, yeni bir nesne oluşturulur ve kurucusundan miras alınır.prototype .

Örneğin:

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

var foo = new Foo();

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

18

Javascript kalıtımı her yerde açık bir tartışma gibi görünüyor. "Javascript dilinin ilginç durumu" olarak adlandırılabilir.

Buradaki fikir, bir temel sınıf olduğu ve ardından kalıtım benzeri bir özellik (tamamen değil ama yine de) elde etmek için temel sınıfı genişletmenizdir.

Bütün fikir, prototipin gerçekte ne anlama geldiğini anlamaktır. John Resig'in kodunu görene kadar alamadım (yakınjQuery.extend ) bunu yapan bir kod parçası yazana kadar anlamadım ve o, baz2 ve prototip kitaplıklarının ilham kaynağı olduğunu iddia etti.

İşte kod.

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

İşi yapan üç bölüm var. İlk olarak, özellikler arasında döngü oluşturur ve bunları örneğe eklersiniz. Bundan sonra, nesneye daha sonra eklenmek üzere bir kurucu oluşturursunuz. Şimdi, ana satırlar:

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

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

Önce Class.prototypeistediğiniz prototipe yöneltin. Şimdi, tüm nesne değişti, yani düzeni tekrar kendi haline zorlamanız gerekiyor.

Ve kullanım örneği:

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

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

John Resig'in gönderisinin yazdığı Javascript Inheritance'ta bunun hakkında daha fazla bilgi edinin .


2

extendÜçüncü taraf kitaplıklarındaki bazı işlevler diğerlerinden daha karmaşıktır. Örneğin Knockout.js , jQuery'nin yaptığı bazı kontrollere sahip olmayan, minimal düzeyde basit bir tane içerir:

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

2
  • .extends() başka bir sınıfın çocuğu olan bir sınıf yaratın.
    perde arkası Child.prototype.__proto__, değerini, Parent.prototype
    yöntemler miras alınacak şekilde ayarlar .
  • .prototype özellikleri birinden diğerine devralır.
  • .__proto__ Prototip için bir alıcı / ayarlayıcıdır.

Bu .extend olmak () ve olmamalı değil .extends ()?
SJHowe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.