当我在DOM对象上查看getter属性时,控制台中发生了什么?

Sno*_*now 16 javascript console getter prototypal-inheritance

在控制台中运行以下代码时:

console.dir(document);
Run Code Online (Sandbox Code Playgroud)

在Chrome中,我看到了以下内容:

在此输入图像描述

这似乎意味着该domain属性直接在document对象上.但事实并非如此.

console.log(document.hasOwnProperty('domain'));
Run Code Online (Sandbox Code Playgroud)

在Chrome 72中,上升原型链,似乎是Document.prototype:

console.log(Document.prototype.hasOwnProperty('domain'));
console.log(Object.getOwnPropertyDescriptor(Document.prototype, 'domain'));
Run Code Online (Sandbox Code Playgroud)

(在FF 56和其他一些浏览器中,它似乎是在开启HTMLDocument.prototype)

从片段中可以看出,该属性实际上由一个getter和一个setter组成.但是,我认为吸气剂在控制台中显示为(...),就像在此图像中一样,您必须单击它(...)来调用吸气剂.

如果我创建一个类似的对象,其原型包含getter/setter属性,并且我记录了该对象,则在检查时不会调用getter:

// 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);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

对于许多属性,可以看到相同的行为document.例如,您可以在第一个屏幕截图中看到的所有其他属性在其中一个原型对象上看起来都是getter/setter,而且它们都不在其中document:

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

您还可以在window属性和元素上看到这一点.这也发生在FF中.

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

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

是否有可能创建一个具有与这些对象相同的日志记录行为console.dir的对象,其中对象也将立即调用原型链中的任何getter,而不是显示(...)?我该如何修改我的theClass代码段?或者,某些预定义对象(如DOM对象)是否只是常规日志记录行为的例外?

我知道如何以编程方式调用getter,我只是对看似不一致感到好奇.

bri*_*eje 1

是否可以创建一个具有与这些相同的日志记录行为的对象,其中 console.diring 对象也将立即调用原型链中的任何 getter,而不是显示 (...)?

从理论上讲,是的,尽管它不会准确地评估吸气剂(我不确定当您 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);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

工作小提琴:https://jsfiddle.net/vL6smo51/1/

  • 这实际上只是手动调用构造函数中的 getter,并将结果值直接放在实例上,因此记录的对象显示实例上的结果值这一事实一点也不奇怪。不过,这个片段 * 确实 * 显示的一件事(如果你检查 Babel 框)是 StackOverflow 的转译器看起来并没有忠实地转译类字段,看起来 `foo =` 的右侧只是丢失了?想知道发生了什么事。 (2认同)