web-dev-qa-db-ja.com

JavaScriptの継承:Object.createとnew

JavaScriptでは、これら2つの例の違いは何ですか:

前提条件:

function SomeBaseClass(){
}

SomeBaseClass.prototype = {
    doThis : function(){
    },

    doThat : function(){
    }
}

Object.createを使用した継承の例A:

function MyClass(){
}

MyClass.prototype = Object.create(SomeBaseClass.prototype);

新しいキーワードを使用した継承例B

function MyClass(){
}

MyClass.prototype = new SomeBaseClass();

どちらの例も同じことをしているようです。どちらを選択するのですか?

追加の質問:以下のリンク(15行目)のコードを検討してください。関数の独自のコンストラクターへの参照がプロトタイプに格納されています。なぜこれが便利なのですか?

https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js

抜粋(リンクを開きたくない場合):

THREE.ImageLoader.prototype = {

    constructor: THREE.ImageLoader
}
120
ChrisRich

あなたの質問であなたはBoth examples seem to do the same thingと言った、それは全く真実ではない、なぜなら

最初の例

function SomeBaseClass(){...}
SomeBaseClass.prototype = {
    doThis : function(){...},
    doThat : function(){...}
}
function MyClass(){...}
MyClass.prototype = Object.create(SomeBaseClass.prototype);

この例では、SomeBaseClass' prototypeを継承していますが、SomeBaseClassにプロパティがある場合はどうなりますか

function SomeBaseClass(){ 
    this.publicProperty='SomeValue'; 
}

そして、あなたがそれを

var obj=new MyClass();
console.log(obj.publicProperty); // undefined
​console.log(obj);​

objオブジェクトには、 この例では のようなpublicPropertyプロパティはありません。

あなたの2番目の例

MyClass.prototype = new SomeBaseClass();

constructor関数を実行して、SomeBaseClassのインスタンスを作成し、SomeBaseClassオブジェクト全体を継承しています。したがって、使用する場合

    var obj=new MyClass();
    console.log(obj.publicProperty); // SomeValue
    console.log(obj);​

この場合、そのpublicPropertyプロパティは、 この例では のようなobjオブジェクトでも使用できます。

Object.createは一部の古いブラウザでは使用できないため、その場合は次を使用できます。

if(!Object.create)
{
    Object.create=function(o){
        function F(){}
        F.prototype=o;
        return new F();
    }
}

上記のコードは、使用できない場合はObject.create関数を追加するだけなので、Object.create関数を使用できます。上記のコードはObject.createが実際に行うことを説明していると思います。それが何らかの形で役立つことを願っています。

110
The Alpha

どちらの例も同じことをしているようです。

それはあなたの場合に当てはまります。

どちらを選択するのですか?

SomeBaseClassに関数本体がある場合、これはnewキーワードで実行されます。これは通常、意図されていません-プロトタイプチェーンをセットアップするだけです。場合によっては、プライベートスコープの変数がすべてのMyClassインスタンスで共有されているオブジェクトを実際にinstantiateするため、深刻な問題を引き起こす可能性さえあります。同じ特権メソッドを継承するため。他の副作用が考えられます。

したがって、通常はObject.create。ただし、一部のレガシーブラウザではサポートされていません。これは、new-アプローチが頻繁に(明らかな)害を与えないため、あまりにも頻繁に表示される理由です。 この答え もご覧ください。

39
Bergi

Object.create()を意図したとおりに使用すると、違いが明らかになります。実際、それはあなたのコードからprototype Wordを完全に隠します、それは内部で仕事をします。 Object.create()を使用すると、次のようになります。

_var base =  {
    doThis : function(){
    },

    doThat : function(){
    }
};
_

そして、これから他のオブジェクトを拡張/継承できます

_var myObject = Object.create( base );
// myObject will now link to "base" via the prototype chain internally
_

したがって、これは別の概念であり、より「オブジェクト指向」の継承方法です。たとえばObject.create()を使用してすぐに使用できる「コンストラクター関数」はありません。しかしもちろん、これらのオブジェクト内で自己定義constructor functionを作成して呼び出すこともできます。

Object.create()を使用する1つの引数は、Javascriptを使用するよりもnaturalからmix/* inherit *に見える場合があることですデフォルトway

8
jAndy

私はJavaスクリプトの専門家ではありませんが、ここでは "Object.create"と "new"の違いを理解する簡単な例を示します。

ステップ1:いくつかのプロパティとアクションで親関数を作成します。

function Person() {

this.name = 'venkat';

this.address = 'dallas';

this.mobile='xxxxxxxxxx'

}

Person.prototype.func1 = function () {

    return this.name + this.address;
}

ステップ2:Newキーワードを使用して、Person関数の上に拡張する子関数(PersonSalary)を作成します。

function PersonSalary() {
    Person.call(this);
}
PersonSalary.prototype = new Person();

PersonSalary();

ステップ3:Object.createキーワードを使用して、Person関数の上に拡張する2番目の子関数(PersonLeaves)を作成します。

function PersonLeaves() {
 Person.call(this);
}
PersonLeaves.prototype = Object.create(Person.prototype);


PersonLeaves();

//次に、両方の子関数のプロトタイプを確認します。

PersonSalary.prototype
PersonLeaves.prototype

これらの子関数は両方ともPerson(parent function)プロトタイプにリンクし、そのメソッドにアクセスできますが、newを使用して子関数を作成すると、必要のないすべての親プロパティを含む真新しいオブジェクトを返します。親関数が実行されたくない「新規」を使用するオブジェクトまたは関数。

ここにテイクアウトがあります

親関数のいくつかのメソッドに委任したいだけで、新しいオブジェクトを作成したくない場合は、Object.createを使用するのが最善の方法です。

0
Venkat