我试图理解为什么以下代码有效:
function checkReading () {
if (checkReading.read) {
return;
}
checkReading.read = this.scrollHeight - this.scrollTop === this.clientHeight;
document.registration.accept.disabled = document.getElementById("nextstep").disabled = !checkReading.read;
checkReading.noticeBox.innerHTML = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}
来源:https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight
我正在努力解决的问题是在if(checkReading.read)
函数对象上声明checkReading.read
属性之前如何调用checkReading
。
这是否有效的原因是函数声明,即使直接作为属性(如上所述)完成,也会被提升到其范围的顶部?
因此,在JS引擎完成事件循环的第一个滴答之后,checkReading.read
实际上被提升(移动)到checkReading
函数的顶部?
PS:我知道正常的函数声明被挂起function foo() {..}
到其作用域的顶部,但不确定是否也适用于上述属性。
答案 0 :(得分:2)
我正在努力解决的问题是在
if(checkReading.read)
函数对象上声明checkReading.read
属性之前如何调用checkReading
。
这与功能或吊装无关。您可以访问任何对象上的不存在的属性:
var foo = {};
console.log(foo.bar);

如果该属性不存在,则其返回值为undefined
,强制为false
。
我实际上考虑过伪造的概念,但接下来的代码永远不会到达。或者我错过了什么?
如果条件为false
,则if
语句的正文不执行,即return;
未执行,因此剩下的该功能已被执行。
答案 1 :(得分:2)
问题不在于提升,而在于在这些不同情况下访问未初始化的值时会发生什么。
如果您在读取之前从未声明变量,则会出现ReferenceError:
if (a) { foo(); } // ReferenceError thrown
let a;
......除非它是var
或function
,否则适用吊装:
function home() {
if (a || b()) { foo(); }
var a;
function b() {}
}
但是,对象属性访问是不同的。对象属性访问永远不会抛出ReferenceError。对象属性也无法声明,实际上 - 它们只是被创建/修改/用作对象的一部分。
if (!a.foo) { a.foo = new Foo(); }
// Use a.foo