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
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)
Và 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ư live
và die
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.
.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 đó.
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
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.
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;
}
"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
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
@meder - bạn nên thêm chú thích visum trong câu trả lời của bạn. :) –