web-dev-qa-db-ja.com

プロトタイプが定義されていない理由

これは何百回も聞かれていることは知っていましたが、prototypeの概念を理解できないようです。

これが私のサンプルスクリプトです

var config = {
  writable: true,
  enumerable: true,
  configurable: true
};

var defineProperty = function(obj, name, value) {
  config.value = value;
  Object.defineProperty(obj, name, config);
}


var man= Object.create(null);
defineProperty(man, 'sex', "male");

var person = Object.create(man);
person.greet = function (person) {
    return this.name + ': Why, hello there, ' + person + '.'
}
var p=Object.getPrototypeOf(person);
alert(p.sex);//shows male
person.prototype.age=13;//why there is a error said the prototype is undefined? I thought it supposed be man object...

var child=function(){}
child.prototype.color="red";//why this line doesn't show error? both child and person are an object . 

alert(child.prototype.color);//shows red

var ch=Object.getPrototypeOf(child);

alert(ch.color);//why it is undefined? it is supposed red.

あなたが私にいくつかの助けを与えることができることを願っています...ありがとう。

更新:

Elclanrsの回答に基づいて、皆さんの親切な助けに感謝します。以下は私が学んだことです。

Functionは、javascriptの組み込みオブジェクトの1つです。 3つのフォーマット作成関数オブジェクトは同じです。

var function_name = new Function(arg1, arg2, ..., argN, function_body)
function function_name(arg1, arg2, ..., argN)
{
...
}
var function_name=function(arg1, arg2, ..., argN)
{
...
}

したがって、プロトタイプチェーンを作成するには、関数を作成してから、新しいキーワードを使用して呼び出す必要があります。

Function.prototypeは、すべての関数オブジェクトprototypeへの参照です。

乾杯

13
Joe.wang

コンセプトを混ぜているのではないかと思います。最初に、古典的なプロトタイプの継承を使用してプロトタイプの概念を把握してみてください。そうすれば、すべての新しいObjectに取り掛かることができます。

JavaScriptでは、すべてのオブジェクト(数値、文字列、オブジェクト、関数、配列、正規表現、日付など)にはprototypeがあり、これは-に共通のメソッド(関数)のコレクションと考えることができます。 allそのオブジェクトの現在お​​よび将来のインスタンス。

プロトタイプチェーンを作成するには、関数を作成し、それをnewキーワードで呼び出して、コンストラクターであることを指定する必要があります。コンストラクターは、オブジェクトの新しいインスタンスを構築するために必要なパラメーターを受け取るメイン関数と考えることができます。

これを念頭に置いて、ネイティブオブジェクトを拡張したり、独自の新しいプロトタイプチェーンを作成したりできます。これはクラスの概念に似ていますが、実際にははるかに強力です。

あなたの例と同様に、次のようなプロトタイプチェーンを書くことができます。

// Very basic helper to extend prototypes of objects
// I'm attaching this method to the Function prototype
// so it'll be available for every function
Function.prototype.inherits = function(parent) {
  this.prototype = Object.create(parent.prototype);
}

// Person constructor
function Person(name, age, sex) {
  // Common to all Persons
  this.name = name;
  this.age = age;
  this.sex = sex;
}

Person.prototype = {
  // common to all Persons
  say: function(words) {
    return this.name +'says: '+ words;
  }
};

// Student constructor   
function Student(name, age, sex, school) {
  // Set the variables on the parent object Person
  // using Student as a context.
  // This is similar to what other laguanges call 'super'
  Person.call(this, name, age, sex);
  this.school = school; // unique to Student
}

Student.inherits(Person); // inherit the prototype of Person

var mike = new Student('Mike', 25, 'male', 'Downtown'); // create new student

console.log(mike.say('hello world')); //=> "Mike says: hello world"

新しいバージョンのJavaScript(EcmaScriptを読む)では、オブジェクトを処理して拡張するための新しい方法が追加されました。しかし、それは古典的なプロトタイプの継承とは少し異なり、より複雑に見えます。JSがどのように機能するかについての知識があれば、それがどのように機能するかを本当に理解するのに役立ちます。さらに、古いブラウザーでは機能しません。そのため、インターネット上で正確で豊富な情報を見つけることができる古典的なパターンから始めることをお勧めします。

10
elclanrs

prototypeプロパティは関数にのみ存在し、personは関数ではありません。 objectです。

何が起こっているのか:

_var man = Object.create(null);         // man (object) -> null
man.sex = "male";

var person = Object.create(man);       // person (object) -> man (object) -> null
person.greet = function () { ... };

var p = Object.getPrototypeOf(person); // man (object) -> null
alert(p.sex);                          // p is the same object as man

person.prototype.age = 13;             // person doesn't have a prototype

var child = function () {};            // child (function) -> Function.prototype
                                       // -> Object.prototype -> null
child.prototype.color = "red";         // child has a prototype

var ch = Object.getPrototypeOf(child); // Function.prototype

alert(ch.color);                       // ch is not the same as color.prototype
                                       // ch is Function.prototype
_

詳細については、この回答を読むことをお勧めします: https://stackoverflow.com/a/8096017/78374

編集:何が起こっているのかをできるだけ少ない言葉で説明するには:

  1. JavaScriptのすべては、プリミティブ値(ブール値、数値、文字列)、およびnullundefinedを除くオブジェクトです。

  2. すべてのオブジェクトには、プログラマーがアクセスできない_[[proto]]_というプロパティがあります。ただし、ほとんどのエンジンでは、このプロパティに___proto___としてアクセスできます。

  3. _var o = { a: false, b: "something", ... }_のようなオブジェクトを作成すると、_o.__proto___は_Object.prototype_になります。

  4. var o = Object.create(something)のようなオブジェクトを作成すると、_o.__proto___はsomethingになります。

  5. var o = new f(a, b, ...)のようなオブジェクトを作成すると、_o.__proto___は_f.prototype_になります。

  6. JavaScriptがoでプロパティを見つけることができない場合、JavaScriptは_o.__proto___でプロパティを検索し、次に_o.__proto__.__proto___などを検索して、プロパティが見つかるか、プロトチェーンがnull(この場合、プロパティはundefinedです)。

  7. 最後に、Object.getPrototypeOf(o)は_o.__proto___を返しますが_o.prototype_は返しません-___proto___は関数を含むすべてのオブジェクトに存在しますが、prototypeは関数にのみ存在します。

13
Aadit M Shah