我有一个类Text,用于处理从输入生成的文本并使其可自定义。例如,我有一个基于给定颜色数组创建颜色按钮的类,这里是代码:
# Example of array of colors given to the function colors: red : "255, 0, 0" blue : "24, 149, 207" green : "74, 165, 76" grey : "202, 202, 202" black : "0, 0, 0" yellow : "183, 118, 4" white : "255, 255, 255" purple : "83, 74, 166" # Here is the method that loop through colors, create a button for each of them and bind the on click event generateColorButtons: (colors) -> colorDiv = $('<div></div>', class : 'colors' ) for color, rgb of colors button = $("<button></button>", class: color ) # itemUniqueId is given to the class when instanciated button.on 'click', @txtColor(@itemUniqueId, rgb) button.appendTo colorDiv return colorDiv # Here is the method that I call on click txtColor: (id, color) -> $("#" + id + ' .addedTxt').css "color", "rgb(" + color + ")"
点击任何颜色按钮都会给我出现此错误&#34; 未捕获的TypeError:undefined不是函数 &#34;,我知道这是因为它无法访问它所绑定的类方法,但有没有办法让它工作或我必须将它声明为常规函数?
更新
原来我只需更改一点点我的点击绑定就可以了,这里是生成颜色的新类:
# Loops through every color variables from the options to create a button for each of them generateColorButtons: (colors) -> colorDiv = $('<div></div>', class : 'colors' ) for color, rgb of colors button = $('<button></button>', class: color ) # Switched from 'on' to 'bind' and created the param to hold the rgb variable because I had scope problems and instead of calling directly the txtColor function, I created an anonymous function with the fat arrow to then call the txtColor in it. button.bind 'click', {param: rgb}, (event) => @txtColor(@itemUniqueId, event.data.param) button.appendTo colorDiv return colorDiv
答案 0 :(得分:0)
您已经明白了这一点,但让我解释一下出了什么问题以及为什么您(想)您需要{param: rgb}
来电中的button.bind
参数。
您的原始代码说:
button.on 'click', @txtColor(@itemUniqueId, rgb)
@txtColor(@itemUniqueId, rgb)
是对txtColor
方法的调用,当button.on
的参数构建时会发生这种情况,即当您调用button.on
而不是点击发生。这跟说的一样:
x = @txtColor(@itemUniqueId, rgb)
button.on 'click', x
这显然不是你想要做的。
显而易见的解决方案(可能是您尝试的下一件事)将是这样的:
button.on 'click', =>
@txtColor(@itemUniqueId, rgb)
当你这样做时,你会发现任何八个按钮上的任何一个按钮都会使用相同的RGB值,而RGB值将是for ... of
循环迭代的最后一个。为什么会这样?当你有这样的事情时:
for k, v of obj
f = -> v
...
每个迭代器都会创建一个新函数,并将其保留在f
但是(这有点但是)这些函数都不会评估v
,直到它们为止调用。所有函数在构建时都会存储对v
的引用,v
的值在每个迭代器上都会发生变化,但v
仍然是同一个变量。结果是,当调用函数时,它们最终都会使用v
的相同值,并且该值将是迭代中的最后一个值v
。
一个例子可能有用。如果你这样做:
fns = for i in [0, 1, 2]
-> i
for f in fns
console.log f()
然后你的控制台最终会有三个2
。 Demo
这个问题在(Java | Coffee)脚本中很常见,所以CoffeeScript有一个solution specifically for this situation (end of this section):
当使用JavaScript循环生成函数时,通常会插入一个闭包装,以确保循环变量被关闭,并且所有生成的函数不只是共享最终值。 CoffeeScript提供
do
关键字,它立即调用传递的函数,转发任何参数。
您可以使用do
重写您的循环:
for color, rgb of colors
do (color, rgb) =>
button = $('<button></button>', class: color)
button.on 'click', =>
@txtColor(@itemUniqueId, rgb)
button.appendTo colorDiv
在评估rgb
时强制do
进行评估,这样您就不会遇到常见的参考问题。