当DOMContentLoaded事件触发时,是否有任何方法可以声明常量,可以在外部访问?
window.addEventListener('DOMContentLoaded', () => {
const button = document.getElementById("button")
})
someObject.on("EventThatWillOnlyOccurAfterDOMContentLoads", () => {
console.log(button.innerHTML) // ReferenceError
})
如果问题是:“ 有没有办法声明一个没有值的常数变量,以后再给它赋一个值?,那么答案是no。
再想一想:在声明之后,常量变量的值必须始终相同;这就是创建常量的关键。
如果您能够创建这样的变量,那将不是真正的常数。看这个例子:
const button //This would throw a SyntaxError but assume it doesn't
window.addEventListener('DOMContentLoaded', () => {
button = document.getElementById("button")
})
someObject.on('Event that may occur either before or after DOMContentLoaded', () => {
//We are unsure what button is here: it might be a DOM node or undefined, or... what?
console.log(button)
})
因此,您不能以这种方式在全局范围内创建一个常量。但是,为什么要在全局范围内声明它呢?
[如果您知道第二个事件不会在DOMContentLoaded
之前触发,则只需移动其声明inside,如下所示:
window.addEventListener('DOMContentLoaded', () => {
const button = document.getElementById("button")
someObject.on("EventThatWillOnlyOccurAfterDOMContentLoads", () => {
console.log(button.innerHTML) // Works perfectly
})
})
这种方法至少和您想要的一样好,如果不是更好的话:
将所有变量保留在事件监听器中:
但是,如果您无法将所有代码都移到DOMContentLoaded
中(例如,因为您想监听一个在其之前触发的事件),那么您还有一个选择:利用ES6的异步结构,这样-称为承诺。
通过使用它们,您的代码可以等待给定的事件(在您的情况下为DOMContentLoaded
),而无需将该代码移入其侦听器内,并且即使多次发出第二个事件也可以工作:
const button = new Promise(setButton => {
window.addEventListener('DOMContentLoaded', () => {
//Resolve the promise when we get the value:
setButton(document.getElementById("button"))
})
})
someObject.on('Event that may occur either before or after DOMContentLoaded', () => {
//This will wait for the promise to resolve if it hasn't done so yet:
button.then(button => {
console.log(button.innerHTML)
})
})
这种方法似乎更复杂,但是当代码变得异步时,到处使用诺言可以简化您的生活。
还请注意,这种方法有其局限性,例如,您不能嵌套其中的两个诺言(如果尝试这样做,则会发现自己处于被询问的情形中):] >
const button = new Promise(setButton => { //How to make this one global as well? const anotherButton = new Promise(setAnotherButton => { window.addEventListener('DOMContentLoaded', () => { setButton(document.getElementById("button")) setAnotherButton(document.getElementById("button2")) }) }) })
相反,您可以将所有DOM元素收集到一个对象中,并使用它来解决您的诺言:
const DOMElements = new Promise(resolve => {
window.addEventListener('DOMContentLoaded', () => {
//Resolve the promise when we get the value:
resolve(Object.freeze({
button: document.getElementById("button"),
anotherButton: document.getElementById("button2")
}))
})
})
someObject.on('Event that may occur either before or after DOMContentLoaded', () => {
//Destructure button:
button.then(({button}) => {
console.log(button.innerHTML)
})
})