我对JavaScript相对较新,并且继续在我使用的第三方库中看到.extend和.prototype。我认为它与Prototype javascript库有关,但我开始认为情况并非如此。这些用于什么?
答案 0 :(得分:128)
Javascript的继承是基于原型的,因此您可以扩展对象的原型,例如Date,Math,甚至是您自己的自定义对象。
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
在上面的代码片段中,我为所有 Date对象(已存在的对象和所有新对象)定义了一个方法。
extend
通常是一个高级函数,它复制您想要从基类扩展的新子类的原型。
所以你可以这样做:
extend( Fighter, Human )
Fighter
构造函数/对象将继承Human
的原型,因此如果您在live
上定义die
和Human
等方法,那么{ {1}}也将继承这些。
更新了澄清说明:
“高级函数”,意思是.extend不是内置的,但通常由jQuery或Prototype等库提供。
答案 1 :(得分:24)
.extend()
,以便轻松地从其他对象创建对象。有关示例,请参阅http://api.jquery.com/jQuery.extend/或http://www.prototypejs.org/api/object/extend。
.prototype
指的是对象的“模板”(如果你想称之为),所以通过向对象的原型添加方法(你在库中看到很多东西要添加到String,Date, Math,甚至Function)这些方法被添加到该对象的每个新实例中。
答案 2 :(得分:18)
jQuery或PrototypeJS中的extend
方法将所有属性从源复制到目标对象。
现在关于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
答案 3 :(得分:18)
Javascript继承似乎就像一场无处不在的公开辩论。它可以被称为“Javascript语言的奇怪案例”。
这个想法是有一个基类,然后扩展基类以获得类似继承的功能(不完全,但仍然)。
整个想法是获得真正意义上的原型。直到我看到John Resig的代码(接近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的帖子中了解更多相关信息。
答案 4 :(得分:2)
第三方库中的某些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;
}
答案 5 :(得分:1)
.extends()
创建一个类,该类是另一个类的子类。Child.prototype.__proto__
将其值设置为Parent.prototype
.prototype
从一个功能继承到另一个功能。.__proto__
是原型的获取者/设置者。答案 6 :(得分:0)
对我来说,这似乎是最清晰,最简单的示例,它只是追加属性或替换现有属性。
function replaceProperties(copyTo, copyFrom) {
for (var property in copyFrom)
copyTo[property] = copyFrom[property]
return copyTo
}