私は比較的JavaScriptに慣れておらず、使用しているサードパーティのライブラリに.extendと.prototypeが表示され続けています。 Prototype javascriptライブラリと関係があると思っていましたが、そうではないと考え始めています。これらは何に使用されますか?
Javascriptの継承はプロトタイプに基づいているため、Date、Math、さらには独自のカスタムオブジェクトなどのオブジェクトのプロトタイプを拡張できます。
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
上記のスニペットでは、all Dateオブジェクト(既存のものとすべて新しいもの)のメソッドを定義しています。
extend
は通常、基本クラスから拡張する新しいサブクラスのプロトタイプをコピーする高レベル関数です。
次のようなことができます:
extend( Fighter, Human )
Fighter
コンストラクター/オブジェクトはHuman
のプロトタイプを継承するため、live
のdie
やHuman
などのメソッドを定義すると、Fighter
_もそれらを継承します。
更新された説明:
.extendを意味する「高レベル関数」は組み込みではありませんが、多くの場合jQueryやPrototypeなどのライブラリによって提供されます。
.extend()
は、他のオブジェクトからオブジェクトを簡単に作成できるように、多くのサードパーティライブラリによって追加されています。 http://api.jquery.com/jQuery.extend/ または http://www.prototypejs.org/api/object/extend を参照してください。
.prototype
はオブジェクトの「テンプレート」(それを呼び出したい場合)を参照するため、オブジェクトのプロトタイプにメソッドを追加することにより(ライブラリでこれをよく見て、String、Date、Math、またはFunction)これらのメソッドは、そのオブジェクトのすべての新しいインスタンスに追加されます。
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
Javascriptの継承は、どこでも開かれた議論のようです。 「Javascript言語の奇妙な事例」と呼ぶことができます。
基本クラスがあり、基本クラスを拡張して継承のような機能を取得するという考え方です(完全ではありませんが、それでも)。
全体のアイデアは、プロトタイプが本当に意味するものを取得することです。 John Resigのコード(jQuery.extend
が実行する内容に近い)がそれを実行するコードチャンクを作成するまで、私はそれを取得できませんでした。
これがコードです。
/* 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;
};
})();
仕事をしている3つの部分があります。最初に、プロパティをループし、インスタンスに追加します。その後、後でオブジェクトに追加するためのコンストラクターを作成します。今、キー行は次のとおりです。
// 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の継承 の投稿を参照してください。
サードパーティライブラリの一部の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;
}