【问题标题】:What is happening in the console when I look at getter properties on DOM objects?当我查看 DOM 对象的 getter 属性时,控制台中发生了什么?
【发布时间】:2019-07-13 23:33:08
【问题描述】:

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

console.dir(document);

在 Chrome 中,我看到,除其他外:

这似乎暗示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 上)

从sn-p可以看出,属性实际上是由getter和setter组成的。但是,我的印象是 getter 在控制台中显示为 (...),就像在 this image 中一样,您必须单击 (...) 才能调用 getter。

如果我创建一个类似的对象,其原型包含一个 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);

document 上的许多属性都可以看到相同的行为。例如,您可以在第一个屏幕截图中看到的所有其他属性也似乎是其中一个原型对象的 getter/setter,它们都不在 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.diring 对象也将立即调用原型链中的任何 getter,而不是显示(...)?我将如何修改我的theClass sn-p?或者,某些预定义的对象(如 DOM 对象)是否只是对正常的日志记录行为有一个例外?

我知道如何以编程方式调用 getter,我只是对表面上的不一致感到好奇。

【问题讨论】:

  • 实际上,如果您查看document__proto__ 链,您会发现domain getter 和setter 与(...) 评估。我认为您在那里看到的值不是Document 接口的domain 属性,正如您在本规范中看到的那样:html.spec.whatwg.org/multipage/dom.html#document,而是 DOM 元素的属性,它得到以某种方式列举。简而言之,在我看来,这样的属性特别是由console.dir 评估的属性,而不是Document 接口的属性值。
  • 我认为真正做到这一点的唯一合理方法是通过使用自调用匿名函数评估其值来覆盖theClass 中的属性。这将导致与您提到的 document 相同的结果,从而导致对象具有 foo 评估和 foo 其祖先中的 getter 和 setter。 jsfiddle.net/vL6smo51 。我看到的唯一合乎逻辑的条件是Document 正在评估HTMLDocument 的一些属性,因此是值。
  • 这似乎是a chrome devtools bug。奇怪的是,你也可以在 FF 中重现它……
  • @Bergi 这个问题看起来有点相似,但它不是一回事 - 在那里,getter 显示在原型链的所有级别上,这是不同的从 getter 被自动调用。

标签: javascript console getter prototypal-inheritance


【解决方案1】:

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

从理论上讲,是的,尽管它不会准确评估 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);

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

【讨论】:

  • "我不确定您看到的值是否在您使用 console.dir 时被评估" - 不,它在您实例化 theClass 并初始化foo自己的财产。
  • @Bergi 我指的是他发布的document 示例,而不是他提供的theClass 示例。我知道这个例子(theClass)console.dir 不评估属性,我想知道它是否与document 一起使用,因为它很奇怪。
  • 这实际上只是在构造函数中手动调用 getter,并将结果值放在实例上,因此记录的对象在实例上显示结果值这一事实一点也不奇怪.虽然,这个 sn-p 确实 显示的一件事(如果您选中 Babel 框)是 StackOverflow 的转译器看起来并没有忠实地转译类字段,它看起来像 @987654331 的右侧@只是迷路了?想知道发生了什么。
【解决方案2】:

有几点需要注意。

  1. 首先,console.* 语句(.error 除外)是异步的,您通过引用传递文档对象,实际上在将其传递给 console.FN 和实际输出到日志窗口之间可能会发生变化。
  2. 其次,就查询而言,浏览器可以通过 JS API 直接访问更多内容。
  3. 第三,文档本身可能有一个继承链,其中包括不属于文档实例本身的域之类的东西。
  4. 第四,并非所有属性都可以在设计上进行迭代,但仍可能显示在日志中(参见上面的 #2)

【讨论】:

  • 我认为您的意思是“可枚举”或“可访问”,而不是“可迭代”。
  • 你能扩展#3吗?
  • 虽然记录的对象确实会由于异步更改而出现不同的外观,但这不是这里发生的事情,请参阅jsfiddle.net/c5npxr7z/1(您可以多次打开和关闭记录的对象,但它永远不会获得domain 的自有财产。
  • 2.好主意,当记录对象时,浏览器看起来正在执行 internal 例程,请参阅jsfiddle.net/0xsg3z48/2 - 在记录document 时永远不会调用Document.prototype 上的自定义getter!但是,如果您在原型上使用delete 属性,则在记录document 时不会出现关联的属性。因此,用自定义对象模拟这种行为可能是不可能的。
【解决方案3】:

document.hasOwnProperty() 语句仅在对象具有指定属性作为其自己的属性(而不是继承它)时才返回 true。在这种情况下,域属性是从 HTMLDocument 对象继承的。 HTMLDocument 是文档的原型。所以它返回 false。

【讨论】:

  • 是的 - 这不是我们要求的
猜你喜欢
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 2018-06-03
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多