Что происходит в консоли, когда я смотрю свойства геттера для объектов DOM? - PullRequest
0 голосов
/ 20 февраля 2019

При запуске следующего кода в консоли:

console.dir(document);

В Chrome я вижу, среди прочего:

enter image description here

Кажется, это означает, что свойство domain находится непосредственно на объекте document.Однако это не так.

console.log(document.hasOwnProperty('domain'));

В Chrome 72, поднимаясь по цепочке прототипов, он, кажется, находится на Document.prototype:

console.log(Document.prototype.hasOwnProperty('domain'));
console.log(Object.getOwnPropertyDescriptor(Document.prototype, 'domain'));

(в FF 56 и, возможно, в некоторых других браузерах он отображается вместо HTMLDocument.prototype)

Как видно из фрагмента,свойство на самом деле состоит из геттера и сеттера.Но у меня сложилось впечатление, что геттеры отображаются в консоли как (...), как в это изображение , которое вы должны были нажать на (...), чтобы вызвать геттер.

Если я создаю подобный объект, прототип которого содержит свойство getter / setter, и я регистрирую объект, метод get не вызывается при его исследовании:

// look at results in Chrome's browser console, not snippet console
class theProto {
  get foo() {
    return 'fooVal';
  }
  set foo(arg) {
    // do something
  }
}
class theClass extends theProto {
}
const instance = new theClass();
console.dir(instance);

enter image description here

Такое же поведение можно наблюдать для многих свойств document.Например, все других свойств, которые вы видите на первом снимке экрана, также являются геттерами / сеттерами для одного из объектов-прототипов, и ни одно из них не включено в document:

console.log(
  ['dir', 'doctype', 'documentElement', 'documentURI', 'embeds', 'fgColor', 'firstChild', 'firstElementChild']
  .some(prop => document.hasOwnProperty(prop))
);

Это также можно увидеть в свойствах window и элементах.Это происходит и в FF.

const input = document.createElement('input');
// console.dir(input);

// but the own property list is empty!
console.log(Object.getOwnPropertyNames(input));
<img src="https://i.stack.imgur.com/R5u3S.png">

Возможно ли создать объект с таким же поведением ведения журнала, как и эти, когда console.dir объект также немедленно вызовет любые геттеры в цепочке прототиповвместо отображения (...)?Как мне изменить мой theClass фрагмент?Или же некоторые предопределенные объекты (например, объекты DOM) просто имеют исключение из обычного поведения ведения журнала?

Я знаю, как программно вызывать геттеры, мне просто любопытно, как выглядит несоответствие.

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019
Оператор

document.hasOwnProperty() возвращает true только в том случае, если объект имеет указанное свойство в качестве своего собственного свойства (в отличие от его наследования).По этой причине свойство домена наследуется от объекта HTMLDocument.HTMLDocument является прототипом документа.Таким образом, он возвращает ложь.

0 голосов
/ 25 февраля 2019

Есть несколько вещей, о которых нужно знать.

  1. Во-первых, операторы console. * (Кроме .error) являются асинхронными, вы передаете объект документа по ссылке, который может фактически измениться между передачей его в console.FN и фактическим выводом.в окно журнала.
  2. Во-вторых, у браузера есть доступ к большему, чем вы могли бы через JS API напрямую с точки зрения опроса.
  3. В-третьих, сам документ может иметь цепочку наследования, которая включает такие вещи, как домен, который не является частью самого экземпляра документа.
  4. В-четвертых, не все свойства являются итеративными по своей структуре, но все равно могут отображаться в журнале (см. № 2 выше)
0 голосов
/ 20 февраля 2019

Можно ли создать объект с таким же поведением ведения журнала, как это, когда console.diring объекта также немедленно вызовет любые методы получения в цепочке прототипов вместо отображения (...)?

С технической точки зрения да, несмотря на то, что он не будет точно оценивать геттеры (я не уверен, оцениваются ли значения, которые вы видите, когда вы их задаете console.dir).Вам необходимо оценить недвижимость.Однако использование hasOwnProperty вернет true.

// look at results in Chrome's browser console, not snippet console
class theProto {
  get foo() {
    return 'fooVal';
  }
  set foo(arg) {
    // do something
  }
}
class theClass extends theProto {
   foo = (() => theProto.prototype.foo)(); // or, really, just (() => this.foo)();
}
const instance = new theClass();
console.dir(instance);

enter image description here

Рабочая скрипка: https://jsfiddle.net/vL6smo51/1/

...