2013-03-02 18 views
19

私はJavaScript関数オブジェクトを以下のように持っています。Javascript関数オブジェクトのプロパティ

var addNum = function(num1, num2) { 
     return num1 + num2; 
} 

は、今私は、私は上記のコードのためのプロトタイプチェーンを理解したかった

addNum.divide() 

アクセスしようとします。上記の例では、addNumはdivide()、Function.prototype、Object.prototypeの順に検索されています。

しかし、私の質問は(addNumが除算検索されるだろうことができますどのように、上記の例である)

それはのようなものを参照しています。

私はそれがaddNumは(除算検索されるだろうという行を理解することができませんでした
var addNum = function(num1, num2) { 

this.divide = function(){} 

      return num1 + num2; 
    } 

私は同じことを理解するのに役立ちます。

+0

私はChromeでコードを実行それは言う:Uncaught TypeError:オブジェクト関数(​​num1、num2){ return num1 + num2; } '分割'方法がありません – andri

+0

これはアーキテクチャ上の問題ではありませんか?実際にはdivideはaddNumの子関数ではありません。むしろ、それらは親クラス/オブジェクトを持ち、変数とプロパティを共有して数学を行うことができますか? –

+0

私はこの行をhttp://doctrina.org/Javascript-Objects-Prototypes.html – testndtv

答えて

48

これはあなたの質問に答えることはできませんが、いくつかの洞察力を与えるかもしれません。次の例を考えてみます。

var Person = (function() { 
    var Person = function (name) { 
     this.name = name; 
    } 

    Person.greet = function() { 
     console.log("Hello!"); 
    } 

    Person.prototype = { 
     greet: function() { 
      console.log('Hello, my name is ' + this.name); 
     } 
    }; 
    return Person; 
})(); 

var bob = new Person("Bob"); 

Person.greet(); // logs "Hello!" 
bob.greet(); // logs "Hello, my name is Bob 

ファンクションオブジェクト "Person"には直接greetというプロパティがあります。 OOPでは、Person関数(Person.greet())から直接呼び出すことができる静的メソッドと考えることができます。 PersonオブジェクトをPersonコンストラクタから "インスタンス化"すると、その新しいオブジェクト "bob"がPerson.prototypeオブジェクトのメソッドを参照するようになりました。今すぐbob.greet()を呼び出すと、プロトタイプオブジェクトのgreet関数が使用されます。

希望に役立ちます。

+0

私はこの例が気に入っていますが、これは実際にプロトタイプの継承の可能性をよく説明しています.Javascriptの可能性とprototypalのアイデアをさらに示すために 'Function'コンストラクタを拡張することもできる継承。例のおかげで – gmaliar

+0

ありがとうございます。なぜPerson.prototype.constructorが挨拶になるのですか、Personはしないのですか? – Martian2049

1

あなたはコンストラクタ関数としてaddNumを使用した場合いいえ、あなたの最後のコードのみが理にかなって:しかし

var instance = new addNum(); 
instance.divide(); 

、関数はオブジェクトであるので、以下は有効な次のようになります。この中

var addNum = function(num1, num2) { 
     return num1 + num2; 
} 
addNum.divide = function() {} 

ケースdivideは、addNum自体のプロパティであり、プロトタイプの1つではありません。

+0

実際に私はhttp://doctrina.org/Javascript-Objects-Prototypes.htmlでこれを読んでいます – testndtv

+0

はい、そうです。私はそれを少し明確にするために最後の文章を更新しました。 –

0

プロトタイプの継承を理解するには、最初はやや不明ですが、名前が示すように、JavaScriptにはいくつかのプロトタイプがあり、Functionの1つです。

新しい関数を作成するときはいつでも、typeofコマンドでその型をチェックすることができます。あなたのケースでは:

var a = function(a,b) { return a + b; } 

それは"function"を返しますので、あなたのa変数複数のメソッドに追加するには2つの方法があります。 @Keith Morrisが示唆しているように、新しいコンストラクタを作成し、その内部のメソッドを持って戻すことができます。これはまた好ましい方法です。なぜなら、基本オブジェクトを、それらによって表される各オブジェクトに拡張されるプロトタイプメソッドで汚染しないからです。

意味、私が代わりにこれを行う場合:

Function.prototype.divide = function(a, b) { return a/b; } 

私が今できるa.divide(2, 1);をし、それが2を返します。しかし、例えばjQueryを使用してjQuery.divide(2,1)を実行した場合、私は2も取得します。なぜなら、関数の直接のスコープ内でそれを見つけることを試みるからです。そうでない場合は、そのプロトタイプに移動します。

これはあなたに少しうまく説明します。

17

自分で言うとおり、の機能はオブジェクトです。意志の機能を割り当てることができるプロパティとメソッド::関数は、ちょうどオブジェクトリテラル、配列、または何か他のもののようなJSでオブジェクトです。この場合

var someAnonFunction = function(foo) 
{ 
    console.log(this); 
    console.log(this === someAnonFunction);//will be false most of the time 
}; 
someAnonFunction.x = 123;//assign property 
someAnonFunction.y = 312; 
someAnonFunction.divide = function() 
{ 
    console.log(this === someAnonFunction);//will be true most of the time 
    return this.x/this.y;//divide properties x & y 
}; 
someAnonFunction.divide(); 

、で参照される関数オブジェクトは、割り当てられていますdivideと呼ばれる無名関数への参照です(無名関数への参照は、とにかくダビングされました)。したがって、ここにはプロトタイプの関与はありません。あなた自身そう言うと、断っておく:おそらくこれは、より明確である

console.log(someAnonFunction.toString === Function.prototype.toString);//functions are stringified differently than object literals 
console.log(someAnonFunction.hasOwnProperty === Object.prototype.hasOwnProperty);//true 

または、::メソッド/プロパティ呼び出しがに解決する方法の簡単な方式ですべてのオブジェクトは、ちょうどこれを試して、バックObject.prototypeにさかのぼることができますJSの値:

[  F.divide  ]<=========================================================\ \ 
F[divide] ===> JS checks instance for property divide       | | 
/\ ||                   | | 
|| || --> property found @instance, return value-------------------------------| | 
|| ||                   | | 
|| ===========> Function.prototype.divide could not be found, check prototype | | 
||  ||                  | | 
||  ||--> property found @Function.prototype, return-----------------------| | 
||  ||                  | | 
||  ==========> Object.prototype.divide: not found check prototype?  | | 
||   ||                 | | 
||   ||--> property found @Object.prototype, return---------------------|_| 
||   ||                 |=| 
||   =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X| 
||                    \/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined 

したがって、あなたは上記のコードはプロトタイプを使用して仕事をしたい場合、あなたは(この場合は、Function.prototype)種類の試作品を強化する必要がありますことを、次の。実際には"ネイティブ"プロトタイプを変更することが推奨されないことを知っていますか?まだ:両方の場合において

Function.prototype.divide = function (a, b) 
{ 
    a = +(a || 0);//coerce to number, use default value 
    b = +(b || 1) || 1;//division by zeroe is not allowed, default to 1 
    return a/b; 
}; 
function someFunction() 
{ 
    return 'someString'; 
}; 
var another = function(a, b) 
{ 
    return a + b; 
}; 
someFunction.divide(12, 6);//will return 2 
another.divide(12, 4);//3 

、名前(someFunction又はanother)によって参照される機能オブジェクトは、見つからないdivideというプロパティ、スキャンされます。しかし、そのようなプロパティが見つかるFunction.prototypeをスキャンします。
そうでない場合、JSはObject.prototypeもチェックし、失敗した場合は最終的にエラーが発生します。

What makes my.class.js so fast?(プロトタイプチェーンとの取引)
Objects and functions in javascript(機能の要約<は=> < =>コンストラクタオブジェクト)
What are the differences between these three patterns of "class" definitions in JavaScript?を:私はしばらく前にこのテーマにSO上で非常に長い答えを掲載しました


Javascript - Dynamically change the contents of a function(変数とプロパティに割り当てられ、コンテキストが変更され、匿名関数に曖昧に触れる)

+3

ascii芸術のためのupvote – angabriel

+0

私Second eded。 –

2

012を作成することができますstatic法[の並べ替え]として:

var addNum = function(num1, num2) { 
    addNum.divide = function(){return num1/num2;}; 
    return num1 + num2; 
} 
// now you first have to run addNum 
var onethirds = addNum(1,3); //=> 4 
addNum.divide(); //=> 0.333333... 

しかし、それは賢明ではありません。より良いconstructor関数を作成:

function Pair(n1,n2){ 
    n1 = n1 || 1; 
    n2 = n2 || 1; 
    // create instance methods 
    this.add  = function(){return n1+n2;}; 
    this.divide = function(){return n1/n2;}; 
    this.multiply = function(){return n1*n2;} 
} 
var pair1 = new Pair(2,6) 
    ,pair2 = new Pair(1,2); 
pair1.add(); //=> 8 
pair2.divide(); //=> 0.5 
//etc. 

以上の原型的なアプローチ(メソッドがコンストラクタのプロトタイプに、必ずしもすべてのインスタンスに追加されます):

function Pair(n1,n2){ 
    this.n1 = n1 || 1; 
    this.n2 = n2 || 1; 
    // create prototype methods (once) 
    if (!Pair.prototype.add){ 
    var proto  = Pair.prototype; 
    proto.add  = function(){return this.n1+this.n2;}; 
    proto.divide = function(){return this.n1/this.n2;}; 
    proto.multiply = function(){return this.n1*this.n2;} 
    } 
} 

Reading stuff

関連する問題