JavaScript: для чего используются .extend и .prototype?
Я относительно новичок в JavaScript и продолжаю видеть .extend и .prototype в сторонних библиотеках, которые я использую. Я думал, что это связано с библиотекой JavaScript Prototype, но я начинаю думать, что это не так. Для чего они используются?
Ответы
Ответ 1
Наследование Javascript основано на прототипе, поэтому вы расширяете прототипы таких объектов, как Date, Math и даже ваши собственные пользовательские.
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
В вышеприведенном фрагменте я определяю метод для всех объектов Date (уже существующих и всех новых).
extend
обычно является функцией высокого уровня, которая копирует прототип нового подкласса, который вы хотите расширить из базового класса.
Итак, вы можете сделать что-то вроде:
extend( Fighter, Human )
И конструктор/объект Fighter
наследует прототип Human
, поэтому, если вы определяете такие методы, как live
и die
на Human
, тогда Fighter
также наследует их.
Обновлено разъяснение:
"функция высокого уровня" означает, что .extend не встроен, но часто предоставляется библиотекой, такой как jQuery или Prototype.
Ответ 2
.extend()
добавляется многими сторонними библиотеками, чтобы упростить создание объектов из других объектов. Для некоторых примеров см. http://api.jquery.com/jQuery.extend/ или http://www.prototypejs.org/api/object/extend.
.prototype
относится к "шаблону" (если вы хотите называть его) объекта, поэтому, добавляя методы к прототипу объекта (вы видите это в библиотеках, чтобы добавить в String, Date, Math, или даже функция) эти методы добавляются к каждому новому экземпляру этого объекта.
Ответ 3
Метод extend
, например, в jQuery или PrototypeJS, копирует все свойства из источника в целевой объект.
Теперь о свойстве prototype
, он является членом объектов функции, он является частью ядра языка.
Любая функция может использоваться как constructor для создания новых экземпляров объектов. Все функции имеют это свойство prototype
.
Когда вы используете оператор new
с объектом функции, будет создан новый объект, и он наследует его конструктор prototype
.
Например:
function Foo () {
}
Foo.prototype.bar = true;
var foo = new Foo();
foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
Ответ 4
Наследование 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 Inheritance by John Resig.
Ответ 5
Некоторые функции 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;
}
Ответ 6
.extends()
создайте класс, который является дочерним для другого класса.
за кулисами
Child.prototype.__proto__
устанавливает значение Parent.prototype
, поэтому методы наследуются.
.prototype
наследует функции от одного к другому.
-
.__proto__
является геттером/сеттером для прототипа.