JavaScript: Untuk apa .extend dan .prototype digunakan?

122

Saya relatif baru mengenal JavaScript dan terus melihat .extend dan .prototype di pustaka pihak ketiga yang saya gunakan. Saya pikir itu ada hubungannya dengan perpustakaan javascript Prototipe, tapi saya mulai berpikir bahwa bukan itu masalahnya. Untuk apa ini digunakan?

Andrew
sumber

Jawaban:

136

Pewarisan Javascript berbasis prototipe, jadi Anda memperluas prototipe objek seperti Tanggal, Matematika, dan bahkan objek kustom Anda sendiri.

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

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

Dalam potongan di atas, saya mendefinisikan metode untuk semua objek Tanggal (yang sudah ada dan yang baru).

extend biasanya adalah fungsi tingkat tinggi yang menyalin prototipe subkelas baru yang ingin Anda kembangkan dari kelas dasar.

Jadi Anda bisa melakukan sesuatu seperti:

extend( Fighter, Human )

Dan Fighterkonstruktor / objek akan mewarisi prototipe Human, jadi jika Anda mendefinisikan metode seperti livedan diedi Humankemudian Fighterjuga akan mewarisi mereka.

Klarifikasi yang Diperbarui:

"fungsi tingkat tinggi" yang berarti .extend tidak built-in tetapi sering disediakan oleh perpustakaan seperti jQuery atau Prototype.

meder omuraliev
sumber
75
Arti "fungsi tingkat tinggi" .extendtidak built-in tetapi sering disediakan oleh perpustakaan seperti jQuery atau Prototipe.
visum
13
Saya akan menambahkan bahwa tidak disarankan untuk memperluas prototipe objek asli di JS
framp
1
@meder - Anda harus menambahkan komentar visum dalam jawaban Anda. :)
Manish Gupta
9
Dalam pemrograman Javascript modern, merupakan kebiasaan memperlakukan benda global dan asli seperti elemen kamar mandi umum; Anda tidak dapat menghindari masuk ke sana, tetapi Anda harus mencoba meminimalkan kontak dengan permukaan. Ini karena changing the native objects can break other developer's assumptions of these objects,menyebabkan bug javascript yang seringkali membutuhkan waktu berjam-jam untuk melacaknya. Kalimat utama pada jawaban ini tampaknya salah menggambarkan praktik javascript yang berharga ini.
Ninjaxor
24

.extend()ditambahkan oleh banyak pustaka pihak ketiga untuk memudahkan pembuatan objek dari objek lain. Lihat http://api.jquery.com/jQuery.extend/ atau http://www.prototypejs.org/api/object/extend untuk beberapa contoh.

.prototype mengacu pada "template" (jika Anda ingin menyebutnya demikian) dari suatu objek, jadi dengan menambahkan metode ke prototipe objek (Anda sering melihat ini di perpustakaan untuk ditambahkan ke String, Tanggal, Matematika, atau bahkan Fungsi) metode tersebut ditambahkan ke setiap kemunculan baru dari objek itu.

pnomolos.dll
sumber
19

The extendMetode misalnya dalam jQuery atau PrototypeJS , salinan semua properti dari sumber ke objek tujuan.

Sekarang tentang prototypeproperti, itu adalah anggota objek fungsi, itu adalah bagian dari inti bahasa.

Fungsi apa pun dapat digunakan sebagai konstruktor , untuk membuat instance objek baru. Semua fungsi memiliki prototypeproperti ini .

Saat Anda menggunakan newoperator dengan pada objek fungsi, objek baru akan dibuat, dan itu akan mewarisi dari konstruktornya prototype.

Sebagai contoh:

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

var foo = new Foo();

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

Warisan Javascript sepertinya menjadi perdebatan terbuka di mana-mana. Ini bisa disebut "Kasus aneh bahasa Javascript".

Idenya adalah bahwa ada kelas dasar dan kemudian Anda memperluas kelas dasar untuk mendapatkan fitur seperti pewarisan (tidak sepenuhnya, tapi tetap saja).

Keseluruhan idenya adalah untuk mendapatkan arti sebenarnya dari prototipe. Saya tidak mendapatkannya sampai saya melihat kode John Resig (mendekati apa yang jQuery.extenddilakukannya) menulis potongan kode yang melakukannya dan dia mengklaim bahwa pustaka base2 dan prototipe adalah sumber inspirasi.

Ini kodenya.

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

Ada tiga bagian yang melakukan pekerjaan itu. Pertama, Anda mengulang properti dan menambahkannya ke instance. Setelah itu, Anda membuat konstruktor untuk kemudian ditambahkan ke objek. Sekarang, baris kuncinya adalah:

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

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

Anda pertama kali mengarahkan Class.prototypeke prototipe yang diinginkan. Sekarang, seluruh objek telah berubah artinya Anda perlu memaksa tata letak kembali ke tempatnya sendiri.

Dan contoh penggunaan:

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

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

Baca lebih lanjut tentang itu di sini di Javascript Inheritance oleh posting John Resig .

ambodi
sumber
2

Beberapa extendfungsi di pustaka pihak ketiga lebih kompleks daripada yang lain.Knockout.js misalnya berisi yang minimal sederhana yang tidak memiliki beberapa pemeriksaan seperti yang dilakukan jQuery:

function extend(target, source) {
    if (source) {
        for(var prop in source) {
            if(source.hasOwnProperty(prop)) {
                target[prop] = source[prop];
            }
        }
    }
    return target;
}
Simon_Weaver
sumber
2
  • .extends() membuat kelas yang merupakan anak dari kelas lain.
    di balik layar Child.prototype.__proto__menetapkan nilainya Parent.prototype
    sehingga metode diwarisi.
  • .prototype mewarisi fitur dari satu sama lain.
  • .__proto__ adalah pengambil / penyetel untuk Prototipe.
humaid
sumber
Haruskah ini bukan .extend () dan bukan .extends ()?
SJHowe