1

私の理解ではObject.hasOwnProperty、オブジェクトに独自のプロパティ名があるかどうか、つまり継承されていないプロパティがあるかどうかをメソッドがチェックするということです。つまり、プロパティa. 存在しない、またはb. 継承されている場合。

私が間違っている場合は修正してください。ただし、これが古典的な継承を使用しない限り、以下のコードではbar継承されませんか? プロパティが継承されたプロパティである場合、メソッドが true を返すのFooはなぜですか? ここで何が間違っていたのですか?hasOwnPropertypropname

また、オブジェクトで をどのように使用しhasOwnPropertyますFooか? ここのコードは、オブジェクト falseをチェックするときに戻ります。Foo

function Foo() {
    this.propname = 'test';
}

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
4

5 に答える 5

5

ここでつまずく点は、Javascript がプロトタイプの継承を使用することです。あなたが見ているのは、実際には継承ではありません。

hasOwnPropertyfalseプロパティが次の場合に返されます。

  1. 存在しません。
  2. 存在しますが、プロトタイプ チェーンにのみ存在します。

コード内の「クラス」は、継承とはまったく関係ありません。オブジェクトにいくつかのプロパティを設定する単なる関数です。

そのオブジェクトはたまたま新しい空のオブジェクトのインスタンスです。newキーワードを使用して関数を呼び出したためです。これがおそらく混乱の原因です。

関数を次のように書き直すことを想像してください。

function foo() {
  var bar = {};
  bar.propname = 'test';
  return bar;
}

var baz = foo();

baz.hasOwnProperty('propname')true が返されることを期待しますか? オブジェクトのプロパティを明示的に定義したためです。

プロパティを宣言する別の方法は、Fooのプロトタイプで宣言することでした。

function Foo() {
  this.bar = 'baz';
}

Foo.prototype.propname = 'test';

var baz = new Foo();

baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false

繰り返しますが、ここで起こっている魔法のようなことはすべてnewキーワードにかかっています。関数を使用して関数を呼び出すと、newの値が新しいオブジェクトに割り当てthisられ、そのオブジェクトのプロトタイプが、呼び出している関数のプロトタイプと同じになるように設定されます。

これを説明する最も簡単な方法は、hasOwnPropertyonbarにメソッドがあるということですが、呼び出すbar.hasOwnProperty('hasOwnProperty')と が返されfalseます。

これは、hasOwnPropertyメソッドがプロトタイプ チェーンの一番上にあるためObject.prototypeです。Javascript のすべてのオブジェクトはここから継承します。これが、すべてのオブジェクトにhasOwnPropertyメソッドがある理由です。

Javascript でオブジェクト指向プログラミングが難しくなる理由については、良い記事があります。new

于 2015-04-12T09:08:56.810 に答える
3

最初のコード サンプルは次と同等です。

function Foo() {
}

var bar = new Foo();
bar.propname = 'test';

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false

これが、bar.hasOwnProperty('propname')true (プロパティーが bar オブジェクトに明示的に設定されている) をFoo.hasOwnProperty('propname')返し、 false を返す (プロパティーが Foo にまったく設定されておらず、Foo オブジェクト自体にもプロトタイプにも設定されていない) 理由です。

hasOwnPropertyチェックは通常、次のように使用されます。

function Foo() {
    this.propname = 'test';
}
Foo.prototype.inheritedprop = 'test';

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(bar.hasOwnProperty('inheritedprop')); // returns false
于 2015-04-12T09:19:18.327 に答える
2

いいえ、propname実際には、に基づいてによって作成された のインスタンスに設定されます(つまり)。コンストラクターパターンの別の近似により、何が起こっているかが明確になります。FoonewFoo.prototypethis

var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";
于 2015-04-12T09:07:46.650 に答える
1

最初に Foo を作成したときは、後で使用する関数を定義しただけです。

「バー」はその機能をインスタンス化し、本質的にその内部のすべてをアクティブにします。

これらのconsole.logsでこのフィドルをチェックしてください

console.log(Foo)
console.log(bar)

https://jsfiddle.net/7pzwcrjo/

于 2015-04-12T09:13:15.510 に答える
1

まず、Foo クラスの新しいオブジェクトをインスタンス化する必要があります。

この JS ビンは、その点をさらに示しています: http://jsbin.com/zaredowive/2/edit?js,console,output

ご覧のとおり、コンストラクターは、クラス Foo の新しいオブジェクトをインスタンス化するときにのみ呼び出されます。この場合は、bar という変数です。関数 Foo で hasOwnProperty を呼び出しています。この関数はプロパティを保持しません。

于 2015-04-12T09:14:28.470 に答える