新手 - 操纵闭合和循环

时间:2016-06-11 16:48:59

标签: javascript html css

为什么这段代码不起作用的答案是因为:这个方法的问题是你没有提供一个函数作为第二个参数。你正在调用一个函数 - 该函数使事情变成蓝色。它没有返回使事情变成蓝色的功能。因此,您可以立即将事情变成蓝色,当点击发生时,没有什么可以调用的,因为您调用的函数没有返回任何内容。

但是我在第一句话后输了。有人可能会愚蠢吗?也许对代码的直观解释会有所帮助!

代码:https://jsfiddle.net/2yfj89af/1/

var submitSOBox = document.getElementsByClassName("submitSOBox");

for (i = 0; i < submitSOBox.length; i++) {
    submitSOBox[i].addEventListener('click', SOBoxColor(i));
}

function SOBoxColor(i) {
    submitSOBox[i].style.backgroundColor = "blue";
}

5 个答案:

答案 0 :(得分:2)

原因解释:你有这一行:

submitSOBox[i].addEventListener('click', SOBoxColor(i));

这会调用addEventListener,它将函数作为最后一个参数。您提供的SOBoxColor(i)不是函数,而是函数返回的值 - 您可以调用它。要传递函数,您需要传递类似SOBoxColor的内容,因此无需调用它。这是必需的,因为您的浏览器需要知道单击事件发生时要调用的内容。

现在,仅传递SOBoxColor将无法满足您的需求。是的,它会在点击发生时调用SOBoxColor,但您不会传递i值。

要实现这一点,您需要修改一个函数版本,以某种方式预先填充i值作为参数。幸运的是,有一种方法可以使用bind方法创建这样一个修改过的函数,该方法返回相同的函数,但是它绑定了一些东西:

submitSOBox[i].addEventListener('click', SOBoxColor.bind(submitSOBox[i], i));

bind的第一个参数确定在调用SOBoxColor时特殊this对象将代表什么,第二个参数是i将是什么。

现在,这将有效。

但是如果你在this函数中使用SOBoxColor关键字,你可以做得更好,因为那时你甚至不需要i参数:

function SOBoxColor() {
    this.style.backgroundColor = "blue";
}

...你的绑定也可以没有i参数:

submitSOBox[i].addEventListener('click', SOBoxColor.bind(submitSOBox[i]));

它仍然可以更简洁地完成,因为当点击发生时,浏览器已经为我们提供了一个很好的服务:它将this关键字设置为您添加事件处理程序的元素,因此最后,甚至不必明确地将submitSOBox[i]绑定到它。这也可以:

 submitSOBox[i].addEventListener('click', SOBoxColor);

...前提是您更改了SOBoxColor功能以使用this

答案 1 :(得分:0)

当您添加事件监听器时:

submitSOBox[i].addEventListener('click', SOBoxColor(i));

调用函数SOBoxColor(),期望它返回一个在触发事件监听器时调用的函数。

通过返回一个函数,我的意思是这样的:

function SOBoxColor(){
  return function(){
    alert("hello")
    //Do stuff
  }
}

如果您将当前函数替换为上面的函数,则只要触发了单击侦听器,它就会发出“hello”警告。

你会如何解决这个问题?

只需将函数名称放入其中,而无需调用它:

submitSOBox[i].addEventListener('click', SOBoxColor);

现在您将遇到的问题是SOBoxColor

function SOBoxColor(i) {
    submitSOBox[i].style.backgroundColor = "blue";
}

您要将数字作为参数发送,以选择相应的元素,您不能再这样做了。

但是,这不是问题,因为您首先选择的元素不正确。 不要在HTMLCollection submitSOBox中使用它的索引选择它,只需使用this关键字引用当前元素:

function SOBoxColor() {
    this.style.backgroundColor = "blue";
}

因此,您的完整代码现在应该如下所示:

var submitSOBox = document.getElementsByClassName("submitSOBox");

for (var i = 0; i < submitSOBox.length; i++) {
    submitSOBox[i].addEventListener('click', SOBoxColor);
}

function SOBoxColor() {
    this.style.backgroundColor = "blue";
}

答案 2 :(得分:0)

你假设必须通过

来调用函数
functionName();

但这并不是调用函数的唯一方法。您可以输入函数作为参数,使用调用方法:functionName.call(null,args)等。

functionName();做的是让Javascript去,“嘿,我需要找出该函数返回的内容。”所以如果functionName就像

那样
function functionName(){
    console.log("hello!");
    return undefined;
};

Javascript会尝试简化一切。它会运行你的函数,控制台日志“你好!”当它忙于工作时,最后会弄清楚你的函数返回的内容:

undefined;

把它想象成在代数类或其他东西中简化数学表达式。

在你的情况下,你告诉点击事件要调用 SOBoxColor(i)返回的任何内容。所以如果SOBoxColor看起来像这样:

function SOBoxColor(i) {
    submitSOBox[i].style.backgroundColor = "blue";
    return 9000;
}

您的点击事件如下所示:

for (i = 0; i < submitSOBox.length; i++) {
    submitSOBox[i].addEventListener('click', 9000);
}

addEventListener是一个函数,它希望函数作为第二个参数,而不是数字。所以什么都不会发生。

答案 3 :(得分:0)

正如你所说,该函数什么都不返回。实际上它根本不是一个功能。闭包的想法是返回函数,它使用外部作用域中的值。

var submitSOBox = document.getElementsByClassName("submitSOBox");

for (i = 0; i < submitSOBox.length; i++) {
    //changes are possible here but we'll do it later
    submitSOBox[i].addEventListener('click', SOBoxColor(i));
    //in your initial code SOBoxColor(i) returned undefined (no return)
    //and event listener must be a function. Yours was not.
}

//change your function like this:
function SOBoxColor(i) {
    //get the element from collection. 
    //both collection and i are available at this point
    var elem = submitSOBox[i];
    return function(){
       //function knows elem from parent scope
       elem.style.backgroundColor = "blue";
    };
}

我希望这些解释很有帮助。

附加

这是关闭的练习。如果不是那么它将是更简单的解决方案:

var submitSOBox = document.getElementsByClassName("submitSOBox");

for (i = 0; i < submitSOBox.length; i++) {
    submitSOBox[i].addEventListener('click', function(){
           this.style.backgroundColor = "blue";
           //in this context **this** is clicked element 
    });
}

答案 4 :(得分:0)

基本上

submitSOBox[i].addEventListener('click', SOBoxColor(i));

他正在使用函数SOBoxColor,其当前值为i作为参数。 此外,当您向元素添加事件侦听器时,您已经具有指向DOM元素的隐式值。所以只需更改代码:

function SOBoxColor() {
   this.style.backgroundColor = "blue";
}
var submitSOBox = document.getElementsByClassName("submitSOBox");

for (i = 0; i < submitSOBox.length; i++) {
    submitSOBox[i].addEventListener('click', SOBoxColor);//your passing the function
}

使用jQuery也很简单:

$(".submitSOBox").click(function(){ $(this).css("background-color","blue"); });