JavaScript:.extendおよび.prototypeは何に使用されますか?


122

私はJavaScriptに比較的慣れていないため、使用しているサードパーティのライブラリで.extendと.prototypeを確認し続けています。Prototype javascriptライブラリと関係があると思いましたが、そうではないと思い始めています。これらは何に使用されますか?

回答:


136

Javascriptの継承はプロトタイプベースであるため、Date、Mathなどのオブジェクトのプロトタイプ、さらには独自のカスタムプロトタイプまで拡張できます。

Date.prototype.lol = function() {
 alert('hi');
};

( new Date ).lol() // alert message

上のスニペットでは、すべての Dateオブジェクト(既存のオブジェクトとすべての新しいオブジェクト)のメソッドを定義しています。

extend 通常は、基本クラスから拡張する新しいサブクラスのプロトタイプをコピーする高水準関数です。

だからあなたは次のようなことをすることができます:

extend( Fighter, Human )

そして、Fighterコンストラクタ/オブジェクトのプロトタイプを継承しますHumanあなたのようなメソッドを定義しそうならば、liveそしてdieHuman、その後Fighterもこれらを継承します。

明確化の更新:

「高水準関数」は.extendが組み込まれていないことを意味しますが、jQueryやPrototypeなどのライブラリによって提供されることがよくあります。


75
「高水準関数」の意味.extendは組み込みではありませんが、jQueryやPrototypeなどのライブラリーによって提供されることがよくあります。
visum

13
JSでネイティブオブジェクトのプロトタイプを拡張することはお勧めしません
2013年

1
@meder-回答にvisumコメントを追加する必要があります。:)
マニッシュ・グプタ

9
最新のJavascriptプログラミングでは、グローバルとネイティブオブジェクトを公衆トイレの要素のように扱うのが習慣です。そこに入ることは避けられませんが、表面との接触を最小限に抑えるようにしてください。これは、changing the native objects can break other developer's assumptions of these objects,追跡に多くの時間がかかることがあるjavascriptバグにつながるためです。この回答の最初の文は、この貴重なJavaScriptの実践を誤って説明しているようです。
Ninjaxor

24

.extend()他のオブジェクトからオブジェクトを簡単に作成できるように、多くのサードパーティライブラリによって追加されます。いくつかの例については、http://api.jquery.com/jQuery.extend/またはhttp://www.prototypejs.org/api/object/extendを参照してください

.prototype オブジェクトの「テンプレート」(それを呼び出したい場合)を参照するため、オブジェクトのプロトタイプにメソッドを追加することにより(これらはライブラリに多く表示され、文字列、日付、数学、または関数にも追加されます)、これらのメソッドそのオブジェクトのすべての新しいインスタンスに追加されます。


19

extendたとえばjQueryまたはPrototypeJSのメソッドは、ソースから宛先オブジェクトにすべてのプロパティをコピーします。

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

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;
  };
})();

仕事をしている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の継承をご覧ください。


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;
}

2
  • .extends() 別のクラスの子であるクラスを作成します。
    舞台裏 Child.prototype.__proto__でその値を設定してParent.prototype
    、メソッドが継承されるようにします。
  • .prototype ある機能から別の機能を継承します。
  • .__proto__ プロトタイプのゲッター/セッターです。

これは.extend()ではなく、.extends()であるべきではありませんか?
SJハウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.