JavaScript: почему метод Object.hasOwnProperty ведет себя так?

Я понимаю, что Object.hasOwnProperty Метод проверяет, имеет ли объект собственное имя свойства, что означает не наследуемое свойство. Это будет означать, что функция должна возвращать false, когда свойство a. не существует, или б. если это унаследовано.

Поправьте меня, если я ошибаюсь, но если это не использует классическое наследование, не делает bar наследовать от Foo в коде ниже? Почему hasOwnProperty метод, возвращающий истину, когда propname собственность является наследственной собственностью? Что я тут не так понял?

Кроме того, как бы я использовал 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

5 ответов

Решение

Исходный пример кода эквивалентен:

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

Камнем преткновения здесь является то, что Javascript использует прототип наследования. То, что вы видите, на самом деле вовсе не наследование.

hasOwnProperty вернусь false если свойство:

  1. Не существует.
  2. Существует, но только в цепи прототипа.

Класс в вашем коде не имеет ничего общего с наследованием, это просто функция, которая устанавливает некоторые свойства объекта.

Этот объект является экземпляром нового пустого объекта, потому что вы вызвали функцию с new Ключевое слово, которое, вероятно, откуда исходит путаница.

Представьте, что переписываете функцию так:

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

var baz = foo();

Вы ожидаете baz.hasOwnProperty('propname') вернуть истину? Абсолютно потому, что мы явно определили свойство объекта.

Альтернативный способ объявить собственность состоял бы в том, чтобы объявить это на Fooпрототип.

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

Foo.prototype.propname = 'test';

var baz = new Foo();

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

Опять же, магические вещи, происходящие здесь, все вплоть до new ключевое слово. Когда вы вызываете функцию с new функция присваивает значение this быть новым объектом и устанавливает прототип этого объекта таким же, как прототип функции, которую вы вызываете.

Может быть, самый простой способ объяснить это, что есть hasOwnProperty метод на bar, но если вы позвоните bar.hasOwnProperty('hasOwnProperty') это вернется false,

Это потому что hasOwnProperty Метод живет на самом верху цепочки прототипов, на Object.prototype, Каждый объект в Javascript наследуется отсюда, поэтому каждый объект будет иметь hasOwnProperty метод.

Есть хорошая статья о том, почему new делает объектно-ориентированное программирование трудным в Javascript.

Нет, propname на самом деле установлен на примере Foo который создан newна основе Foo.prototype (то есть this). Другое приближение шаблона конструктора проясняет (э), что происходит:

var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";

Сначала вы должны создать новый объект класса Foo.

Эта корзина JS дополнительно иллюстрирует этот момент: http://jsbin.com/zaredowive/2/edit?js,console,output

Как вы можете видеть, конструктор вызывается только тогда, когда вы создаете новый объект класса Foo, который в этом случае является переменной с именем bar. Вы вызываете hasOwnProperty для функции Foo. Эта функция не содержит свойств.

Когда вы впервые написали Foo, вы просто определили функцию, которая будет использоваться позже.

"Бар" создает эту функцию и, по сути, активирует все, что находится внутри нее.

Проверьте эту скрипку с этими console.logs

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

https://jsfiddle.net/7pzwcrjo/

Другие вопросы по тегам