我对JavaScript还比较新,经常在使用第三方库时看到 .extend 和 .prototype。 我以为这与Prototype JavaScript库有关,但我开始觉得这不是这样。 它们有何用途?
我对JavaScript还比较新,经常在使用第三方库时看到 .extend 和 .prototype。 我以为这与Prototype JavaScript库有关,但我开始觉得这不是这样。 它们有何用途?
JavaScript的继承是基于原型的,因此您可以扩展对象的原型,例如Date、Math甚至您自己定义的对象。
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
在上面的片段中,我定义了一个方法,适用于所有日期对象(已经存在的和所有新创建的)。
extend
通常是一个高级函数,它会复制你想要从基类扩展的新子类的原型。extend( Fighter, Human )
Fighter
的构造函数/对象将继承Human
的原型,因此如果您在Human
上定义了live
和die
等方法,则Fighter
也将继承这些方法。
更新的澄清:
“高级函数”意味着.extend不是内置的,而是通常由诸如jQuery或Prototype之类的库提供。
.extend
不是内置功能,但通常由类库(如 jQuery 或 Prototype)提供。 - visum.extend()
被许多第三方库添加以便于从其他对象创建对象。请参见http://api.jquery.com/jQuery.extend/或http://www.prototypejs.org/api/object/extend了解一些示例。
.prototype
指的是对象的“模板”(如果您想这样称呼它的话),因此通过将方法添加到对象的原型中(在许多库中可以看到添加到String、Date、Math甚至Function中),这些方法将添加到该对象的每个新实例中。
比如说在 jQuery 或者 PrototypeJS 中的extend
方法可以将源对象的所有属性复制到目标对象。
至于 prototype
属性,它是函数对象的一个成员,也是语言核心的一部分。
任何函数都可以被用作构造函数,用来创建新的对象实例。所有的函数都有这个 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
jQuery.extend
的代码)才明白了它,他编写了一小段代码来实现它,并声称base2和prototype库是灵感来源。 /* 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;
}
});
在John Resig的Javascript继承文章中,可以了解更多相关技术内容。
.extends()
创建一个继承自另一个类的子类。Child.prototype.__proto__
的值被设置为 Parent.prototype
,因此方法被继承。.prototype
从一个对象继承特性到另一个对象。.__proto__
是原型链的 getter/setter。第三方库中的一些扩展
函数比其他函数更复杂。例如,Knockout.js包含了一个最简单的函数,它没有像jQuery那样进行一些检查:
function extend(target, source) {
if (source) {
for(var prop in source) {
if(source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
}
return target;
}
对我来说,这似乎是最清晰和最简单的示例,它只是附加属性或替换现有属性。
function replaceProperties(copyTo, copyFrom) {
for (var property in copyFrom)
copyTo[property] = copyFrom[property]
return copyTo
}