2010-09-23 6 views
111

Tôi tương đối mới đối với JavaScript và tiếp tục xem .extend và .prototype trong thư viện của bên thứ ba mà tôi đang sử dụng. Tôi nghĩ rằng nó đã làm với thư viện javascript Prototype, nhưng tôi bắt đầu nghĩ rằng đó không phải là trường hợp. Những gì được sử dụng cho?JavaScript: .extend và .prototype được sử dụng để làm gì?

Trả lời

119

Thừa kế của Javascript là dựa trên nguyên mẫu, do đó bạn mở rộng các nguyên mẫu của các đối tượng như Ngày, Toán và thậm chí là các mẫu tùy chỉnh của riêng bạn.

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

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

Trong đoạn trên, tôi xác định một phương pháp để tất cả đối tượng Date (những người đã tồn tại và tất cả những cái mới).

extend thường là hàm mức cao sao chép nguyên mẫu của phân lớp mới mà bạn muốn mở rộng từ lớp cơ sở.

Vì vậy, bạn có thể làm điều gì đó như:

extend(Fighter, Human) 

Fighter constructor/đối tượng sẽ kế thừa nguyên mẫu của Human, vì vậy nếu bạn xác định các phương pháp như livedie trên Human sau đó Fighter cũng sẽ thừa hưởng những.

Làm rõ Cập nhật:

"chức năng cao cấp" có nghĩa là .extend không built-in nhưng thường được cung cấp bởi một thư viện như jQuery hoặc thử nghiệm.

+69

"chức năng cao cấp" có nghĩa là '.extend' không built-in nhưng thường được cung cấp bởi một thư viện như vậy như jQuery hoặc Prototype. – visum

+13

Tôi sẽ thêm nó không được đề xuất để mở rộng các nguyên mẫu của các đối tượng bản địa trong JS – framp

+1

@meder - bạn nên thêm chú thích visum trong câu trả lời của bạn. :) –

22

.extend() được thêm bởi nhiều thư viện của bên thứ ba để giúp dễ dàng tạo đối tượng từ các đối tượng khác. Xem http://api.jquery.com/jQuery.extend/ hoặc http://www.prototypejs.org/api/object/extend để biết một số ví dụ.

.prototype đề cập đến "mẫu" (nếu bạn muốn gọi nó) của đối tượng, do đó, bằng cách thêm phương thức vào nguyên mẫu của đối tượng (bạn thấy điều này rất nhiều trong thư viện để thêm vào Chuỗi, Ngày, Toán hoặc ngay cả chức năng) các phương thức đó được thêm vào mọi cá thể mới của đối tượng đó.

18

Phương thức extend ví dụ: jQuery hoặc PrototypeJS, sao chép tất cả các thuộc tính từ nguồn sang đối tượng đích.

Bây giờ về tài sản prototype, nó là một thành viên của đối tượng hàm, nó là một phần của lõi ngôn ngữ.

Mọi chức năng có thể được sử dụng làm constructor, để tạo các đối tượng đối tượng mới. Tất cả các chức năng đều có thuộc tính prototype này.

Khi bạn sử dụng toán tử new với đối tượng hàm, đối tượng mới sẽ được tạo và nó sẽ được kế thừa từ hàm tạo của nó prototype.

Ví dụ:

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

var foo = new Foo(); 

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

Javascript thừa kế có vẻ là giống như một cuộc tranh luận mở ở khắp mọi nơi. Nó có thể được gọi là "Trường hợp kỳ lạ của ngôn ngữ Javascript".

Ý tưởng là có một lớp cơ sở và sau đó bạn mở rộng lớp cơ sở để có được một tính năng giống như thừa kế (không hoàn toàn, nhưng vẫn).

Toàn bộ ý tưởng là lấy nguyên mẫu thực sự có ý nghĩa gì. Tôi đã không nhận được nó cho đến khi tôi nhìn thấy mã của John Resig (gần với những gì jQuery.extend không) đã viết một đoạn mã mà nó và ông tuyên bố rằng thư viện base2 và nguyên mẫu là nguồn cảm hứng.

Đây là mã.

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

Có ba phần đang thực hiện công việc. Đầu tiên, bạn lặp lại các thuộc tính và thêm chúng vào thể hiện. Sau đó, bạn tạo một constructor cho sau này được bổ sung vào object.Now, các đường chính là:

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

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

Bạn đầu tiên quan điểm Class.prototype để nguyên mẫu mong muốn. Bây giờ, toàn bộ đối tượng đã thay đổi ý nghĩa rằng bạn cần buộc bố cục quay lại với một đối tượng riêng của nó.

Và ví dụ sử dụng:

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

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

đọc thêm về nó ở đây tại Javascript Inheritance by John Resig 's đường bưu điện.

1

Một số chức năng extend trong thư viện của bên thứ ba phức tạp hơn các thư viện khác. Knockout.js ví dụ có chứa một ít đơn giản mà không có một số các kiểm tra rằng jQuery làm:

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