所以我正在学习javascript(?(,我遇到了这种情况,我真的找不到一个直接的答案。
所以我在一个 HTML 页面中有这些段落,我想更改其背景颜色,我工作的代码是这样的:
var colors=['red','pink','blue'];
var div2paragraphs = document.querySelectorAll('#div2 p')
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
(function(paragraph) {
div2paragraphs[paragraph].onmouseover = function(){
this.setAttribute('style', `background-color: ${colors[paragraph]}`)}
div2paragraphs[paragraph].onmouseout = function(){
this.setAttribute('style', 'background-color: white')}
})(paragraph);
}
我也不太明白这里发生了什么,我只是想用整个"function(({}"的东西(据说称为匿名函数?(来做到这一点,但显然在 javascript 中有一种叫做 IIFE 的东西,所以你必须包装函数并传递一个唯一的变量,让它每次在循环中运行, 虽然我仍然不明白为什么我必须用"(段落("结束它。
我在想是否可以通过为每个 setAttribute 操作创建一个函数来做同样的事情,所以我尝试这样写:
var colors=['red','pink','blue'];
var div2paragraphs = document.querySelectorAll('#div2 p')
function changeToColor(color) {
this.setAttribute('style', 'background-color: ' + color);
}
function changeBackWhite() {
this.setAttribute('style', 'background-color: white');
}
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = changeToColor('red');
div2paragraphs[paragraph].onmouseout = changeBackWhite;
}
但无论我做什么,它总是会出现错误:
Uncaught TypeError: this.setAttribute is not a function
或类似的东西。 我认为它与这些情况有关,如果您添加括号,它会在执行其他任何操作之前调用该函数? 所以它不知道"这"是什么? 我不太明白,但无论如何,我对如何用单独的功能编写我上面所做的同样的事情一无所知。 有人能够对此有所了解吗?
我更习惯于Python,所以显然有一些基本概念是不同的......
PS:下面这两个例子有什么区别?
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = function() {
this.style['background-color'] = colors[paragraph];
}
div2paragraphs[paragraph].onmouseout = function() {
this.style['background-color'] = 'white';
}
}
而这个
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = function(){
this.setAttribute('style', `background-color: $(colors[paragraph]`)
}
div2paragraphs[paragraph].onmouseout = function(){
this.setAttribute('style', 'background-color: white')
}
}
为什么第一个(由易卜拉欣·马格里尔提供(有效,而第二个不起作用?
在第一个代码示例中,循环中的 IIFE 完全没用,因为您已经在使用尊重块范围的let
,因此不会发生此问题。以下代码可以正常工作:
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = function() {
this.style['background-color'] = colors[paragraph];
};
div2paragraphs[paragraph].onmouseout = function() {
this.style['background-color'] = 'white';
};
}
注意:您无需使用setAttribute
即可设置style
属性。直接做就行了。
演示:
var colors=['red','pink','blue'];
var div2paragraphs = document.querySelectorAll('#div2 p');
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = function() {
this.style['background-color'] = colors[paragraph];
};
div2paragraphs[paragraph].onmouseout = function() {
this.style['background-color'] = 'white';
};
}
<div id="div2">
<p>AAAA</p>
<p>BBBB</p>
<p>CCCC</p>
</div>
至于第二个代码示例,您的函数需要返回其他函数以分配为事件侦听器。例如,changeColor
应按如下定义:
function changeToColor(color) {
return function() {
this.style['background-color'] = color;
}
}
changeColor
返回的匿名函数将分配给事件侦听器。在您的代码中,changeColor
未返回任何内容,因此undefined
附加到事件侦听器。此外,changeColor
不是事件侦听器本身(它只是一个创建事件侦听器并返回它的函数(,因此this
里面将是全局对象window
。window
没有一个名为setAttribute
的方法,因此会出现错误。
此外,您不需要changeBackWhite
,您可以将changeColor
用于两者(由闭包提供(,如下所示:
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = changeToColor(colors[paragraph]);
div2paragraphs[paragraph].onmouseout = changeToColor('white');;
}
演示:
var colors=['red','pink','blue'];
var div2paragraphs = document.querySelectorAll('#div2 p');
function changeToColor(color) {
return function() {
this.style['background-color'] = color;
}
}
for (let paragraph = 0; paragraph < div2paragraphs.length; paragraph++) {
div2paragraphs[paragraph].onmouseover = changeToColor(colors[paragraph]);
div2paragraphs[paragraph].onmouseout = changeToColor('white');;
}
<div id="div2">
<p>AAAA</p>
<p>BBBB</p>
<p>CCCC</p>
</div>
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Event_handlers
分配事件处理程序时,必须将处理程序函数分配给占位符。
div2paragraphs[paragraph].onmouseover = changeToColor('red');
TypeError
发生在这里。参数为"red"的调用changeToColor
函数的结果(返回值(是一个变量。这不是一个函数。分配的处理程序必须适合原型function(Event e){...}
其中 e 是 Event 类的对象,如 https://developer.mozilla.org/en-US/docs/Web/API/Event
div2paragraphs[paragraph].onmouseout = changeBackWhite;
但是,此行是正确的,因为您将已定义函数的 ID 分配给占位符,然后该占位符可用作真正的处理程序函数。
您需要做的是,重写函数 changeToColor 并将其 ID 分配给占位器
div2paragraphs[paragraph].onmouseover = changeToColor
或者,如果要立即调用该函数,可以使用call
或apply
将其包装在另一个this
引用其所属上下文的函数中(如果调用函数需要this
(。
div2paragraphs[paragraph].onmouseover = function () {
changeToColor.call(this, 'red');
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this