3

私は JavaScript を初めて使用します (今週から学習を開始しました)。CodeCademy コースを修了しました (実際には Objects 1 && 2 の部分だけで、残りは退屈でした)。コンストラクターでプロトタイプの継承を学んだと思っていましたが、Douglas Crockford: Advanced JavaScriptを見始めました。

ビデオの冒頭で、彼は 2 種類の継承について言及しています。だから私はChrome JavaScriptコンソールで遊んで始めて、両方の継承モデルを使って何かをしようとしました.

//create constructor
function MyParent(){ 
    this.name = "joe";
    this.sayHi = function(){ 
        console.log(this.name); 
    }
}

//create child object and inherit from parent
var myChild1 = new MyParent();
myChild1.name
"joe"
myChild1.sayHi()
joe

//add method to MyParent, so it can be accessed from myChild1
MyParent.prototype.sayBye = function(){ console.log("bye");}

myChild1.sayBye()
bye

//create another constructor
function MyParent2(){
    this.sayHi = function(){ 
        console.log("hi"); 
    }
}

//make it inherit from MyParent, overwriting sayHi if object is instance of MyParent2
MyParent2.prototype = new MyParent();

//overwrote sayHi
var myChild11 = new MyParent2(); 
myChild11.sayHi();
hi

//still same as MyParent as its not overwriten in MyParent2
myChild11.name
"joe"

Object.create を使用して同じことを試みたよりも:

//create an object
 var myParent = { 
    name : "joe",
    sayHi : function(){ 
        console.log(this.name) 
    } 
};

//it works
myParent.sayHi()
joe

//create child object
var myChild = Object.create(myParent);
myChild.sayHi()
joe

//add bye method to myChild
myChild.sayBye = function(){ console.log("bye"); }
myChild.sayBye();
bye

//add bye method to myParent - does not overwrite child's bye
myParent.sayBye = function(){ console.log("bye2"); }

//however adding sayBye2 to parent, becomes available on already created child
myParent.sayBye2 = function(){ console.log("bye2"); }
myChild.sayBye2();
bye2
//but its the parent property
myChild.hasOwnProperty("sayBye2")
false

//could make million objects inherit from each other vertically or horizontally
var myChild2 = Object.create(myChild);
myChild2.name
"joe"

これまでのところ、第一印象だけで、私は両方のモデルが好きですが、後者の方が少し好きかもしれません. より表現力と力強さを増しているようです。

このトピックについていくつかの検索を行いましたvs.が、各アプローチの長所と短所を説明する良い記事を見つけることができませんでした (後者以外は新しいブラウザーでのみサポートされていますが、簡単な回避策があります)。私が見つけた残りの投稿は、tl: dr; だけでした。そしてやや退屈。

だから私の質問は、どのタイプの継承を使用する必要があるかです。どちらかに関連する特典はありますか? いずれかの主な短所はありますか?両方をミックスできますか?(例: object を引数として に渡すことができることは知っていますnew Constructor()))

ありがとう

編集: ブラウザーがサポートしていない場合に Object.create() の代替を作成するトリックを見て、ハックがいかに簡単であるかに気付きました。基本的に、空のコンストラクターを作成し、親オブジェクトをプロトタイプとして割り当て、構築されたコンストラクターを新しいオブジェクトとして返します。なんて巧妙なハックでしょう!

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

しかし、その影響は何ですか?知っておくべき落とし穴はありますか?

4

2 に答える 2

3

どちらの方法も同様に強力です。純粋なプロトタイプのアプローチを採用しない場合、真の JavaScript マスターではないという人もいますが、実際にはすべてがプロトタイプの継承にすぎず、スタイルの問題です。

個人的には、古典的なアプローチを使用することを好みnew、関数と一緒にキーワードを使用しconstructorます。

なんで?

  • 古典的なモデルは非常によく知られています。
  • すでに行ってinitいることを行うためだけに、オブジェクトに関数を実装する必要はありません。constructorお気づきかもしれませんが、純粋なプロトタイプのアプローチでは がなく、新しく作成されたオブジェクトの初期化ロジックを実行する必要がある場合はconstructor、初期化関数 (通常は と呼ばれます) を実装する必要があります。init

ただし、純粋なプロトタイプのアプローチは少し冗長であり、古典的な継承を実装する言語に強いバックグラウンドを持たないプログラマーにとって理解しやすいかもしれません。

ところで、古典的なモデルで避けるべきことの 1 つは、上記のようにキーワードを使用して継承するnewことです。これは、親constructorロジックを不必要に実行しており、望ましくない副作用が発生する可能性があるためです。

Object.create以下のように使用する必要があります。

function A(val) { this.val = val; }
A.prototype.alertVal = function () { alert(this.val); };

function B(val) {
    A.call(this, val); //call parent constructor
}

B.prototype = Object.create(A.prototype); //inherit from A
var b = new B('test');
b.alertVal(); //test

結局は好みの問題で、どちらも尊重します。たぶん、他の誰かがいくつかの本当の利点/欠点でこの答えを改善したいと思うでしょうが、私は何も見つけられません.

于 2013-04-08T05:48:11.050 に答える
0

を使用してオブジェクトを構築することnewは悪であると宣言されました。なぜなら、それを使用するのを忘れる可能性があり、追加したプロパティがthisグローバル オブジェクトに追加されてしまうからです。このため、私は 2 番目のアプローチを採用しています。

私が学んだもう 1 つのことは、「古典的な」OOD を JavaScript に適用しようとするべきではないということです。それには、理解すべき独自の方法があり、実際には非常に優れています。JavaScript におけるオブジェクト プログラミングの問題のほとんどは、「クラス」の概念を JavaScript に拡張しようとする試みに起因すると思います。

于 2013-04-08T04:39:07.713 に答える