Ответы:
Наследование в Javascript основано на прототипах, поэтому вы расширяете прототипы таких объектов, как Date, Math, и даже свои собственные.
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
В приведенном выше фрагменте я определяю метод для всех объектов Date (уже существующих и всех новых).
extend
обычно является функцией высокого уровня, копирующей прототип нового подкласса, который вы хотите расширить от базового класса.
Итак, вы можете сделать что-то вроде:
extend( Fighter, Human )
И Fighter
конструктор / объект унаследует прототип Human
, поэтому, если вы определите такие методы, как live
и die
on, Human
тогда Fighter
они также унаследуют их.
Обновленное разъяснение:
"функция высокого уровня", означающая .extend не является встроенной, но часто предоставляется библиотекой, такой как jQuery или Prototype.
changing the native objects can break other developer's assumptions of these objects,
приводит к ошибкам javascript, на отслеживание которых часто может уйти много часов. Кажется, что первое предложение в этом ответе искажает эту ценную практику javascript.
.extend()
добавляется многими сторонними библиотеками, чтобы упростить создание объектов из других объектов. См. Http://api.jquery.com/jQuery.extend/ или http://www.prototypejs.org/api/object/extend для некоторых примеров.
.prototype
относится к «шаблону» (если вы хотите его так называть) объекта, поэтому, добавляя методы к прототипу объекта (вы часто видите это в библиотеках для добавления в String, Date, Math или даже Function) эти методы добавляются к каждому новому экземпляру этого объекта.
extend
Метод, например , в JQuery или PrototypeJS , копирует все свойства от источника до объекта назначения.
Теперь о prototype
свойстве, это член функциональных объектов, это часть ядра языка.
Любую функцию можно использовать в качестве конструктора для создания новых экземпляров объекта. Все функции имеют этоprototype
свойство .
Когда вы используете new
оператор with для объекта функции, будет создан новый объект, который будет унаследован от своего конструктора.prototype
.
Например:
function Foo () {
}
Foo.prototype.bar = true;
var foo = new Foo();
foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
Наследование Javascript повсюду похоже на открытые дебаты. Его можно назвать «Любопытным случаем языка Javascript».
Идея состоит в том, что существует базовый класс, а затем вы расширяете базовый класс, чтобы получить функцию, подобную наследованию (не полностью, но все же).
Вся идея в том, чтобы понять, что на самом деле означает прототип. Я не понял этого, пока не увидел, что код Джона Ресига (близкий к тому, что jQuery.extend
есть) написал фрагмент кода, который это делает, и он утверждает, что библиотеки base2 и прототипов были источником вдохновения.
Вот код.
/* 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;
};
})();
Есть три части, которые делают работу. Сначала вы просматриваете свойства и добавляете их в экземпляр. После этого вы создаете конструктор, который позже будет добавлен к объекту. Теперь ключевые строки:
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
Сначала вы указываете Class.prototype
на желаемый прототип. Теперь весь объект изменился, а это означает, что вам нужно принудительно вернуть макет к его собственному.
И пример использования:
var Car = Class.Extend({
setColor: function(clr){
color = clr;
}
});
var volvo = Car.Extend({
getColor: function () {
return color;
}
});
Узнайте больше об этом здесь, в сообщении Джона Ресига « Наследование Javascript ».
Некоторые extend
функции в сторонних библиотеках сложнее других. Knockout.js, например, содержит минимально простой файл, в котором нет некоторых проверок, которые выполняет jQuery:
function extend(target, source) {
if (source) {
for(var prop in source) {
if(source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
}
return target;
}
.extends()
создать класс, который является потомком другого класса. Child.prototype.__proto__
устанавливает свое значение Parent.prototype
.prototype
наследуют черты от одного к другому..__proto__
является геттером / сеттером для Prototype.
.extend
она не встроена, но часто предоставляется библиотекой, такой как jQuery или Prototype.