我在JavaScript和JQuery中有一个钢琴键盘对象,如下所示:
function Keyboard(name, size, xPos, yPos, octaves) {
this.name = name;
this.size = size;
this.setDimensions = function (){};
this.highlightKeyboard = function (){};
...
etc.
}
它有一堆方法来设置尺寸,使用div键生成键盘,生成引用div类的主要和次要尺度等。
当我按下某个键时,我写了4个方法来突出显示一个主要音阶,当我按下不同的键时,我写了一个小音阶,用另外两个键按下主要和次要三和音。它们都有效,但在编写之后我意识到所有4种方法都使用了大量相同的代码,所以我一直试图通过将大部分代码放入主要的Keyboard对象中的单独方法来进行整合,以便我可以重复调用它们。
我正在整合的问题是让$(document).keypress
个对象与外部代码一起玩得很好。
我想要的是这样的事情(部分代码示例 - 我遗漏了生成键盘的所有代码以及其他所有不相关的代码,因为除了这个问题之外它似乎正常工作):
function Keyboard(name, size, xPos, yPos, octaves) {
this.getMajorTonic = (function(userNote) {
// code to determine myTonic
return myTonic;
});
this.setMajScale = function(myTonic) {
var scale = [];
// code to determine scale[];
return scale;
};
this.setScaleClasses = function(scale) {
// code to determine scale_classes[]
return scale_classes;
};
this.highlightKeyboard = function (scale, scale_classes){};
// code to add highlighted classes to my divs based
// on the values in scale and scale_classes
};
this.findMajorScales = function(userNote);
var myTonic = this.getMajorTonic(userNote);
var scale = this.setMajScale(myTonic);
var scale_classes = this.setScaleClasses(scale);
var highlightKeyboard = this.highlightKeyboard;
$(document).keypress(function (event) {
if (event.which === 109) {
highlightKeyboard(scale, scale_classes)
}
});
};
}
var keys = new Keyboard("piano", 1, 0, 0, 2);
keys.findMajorScales("E");
所需的效果是,当我加载页面时,它会生成一个空白键盘,但是当我按下“m”键时,它会使用this.highlightKeyboard
方法突出显示E大调。所以我想传递this.findMajorScales
方法没有参数的this.highlightKeyboard
方法,然后填写参数,并在按下“m”键时执行方法。大多数一切都有效,包括($document).keypress
对象 - 它执行其他代码,而不是具有正确参数的this.highlightKeyboard
方法。
我如何做到这一点? .bind与它有关吗?我无法弄清楚它是否适用于此处,或者我是否需要做其他事情。
非常感谢!
杰克
答案 0 :(得分:1)
所以我想传递this.findMajorScales方法一个没有参数的this.highlightKeyboard方法,然后填入参数并在" m"键被按下了。
您正在侦听 M ,所以唯一的问题是在正确的上下文中调用highlightKeyboard
。
考虑
var foo = {bar: function () {return this}),
bar = foo.bar;
foo.bar()
将返回什么? (foo
)
bar()
将返回什么? (window
或null
或抛出错误等)
有几种解决方法,您已经提到过Function.prototype.bind
,从概念上讲,您可以更轻松地使用Function.prototype.call
,Function.prototype.apply
甚至传递{{1}通过使用另一个标识符来改变变量。
在任何一种情况下,处理程序中的默认this
将不再是键盘的实例,因为事件来自this
使用document
您有几个选项
Function.prototype.bind
使用var highlightKeyboard = this.highlightKeyboard.bind(this);
$(document).keypress(function (event) {
if (event.which === 109) {
highlightKeyboard(scale, scale_classes);
}
});
// or binding args ahead of time too
var highlightKeyboard = this.highlightKeyboard.bind(this, scale, scale_classes);
$(document).keypress(function (event) {
if (event.which === 109) {
highlightKeyboard();
}
});
// or binding the handler
$(document).keypress(function (event) {
if (event.which === 109) {
this.highlightKeyboard(scale, scale_classes);
}
}.bind(this));
或Function.prototype.call
,需要参考.apply
this
只需使用参考var highlightKeyboard = this.highlightKeyboard;
var me = this;
$(document).keypress(function (event) {
if (event.which === 109) {
highlightKeyboard.call(me, scale, scale_classes);
}
});
this
最后,还有一个解决方案是编写一个生成所需内容的函数,这与var me = this;
$(document).keypress(function (event) {
if (event.which === 109) {
me.highlightKeyboard(scale, scale_classes);
}
});
正在做的非常相似,但在不支持.bind
的环境中受支持(阅读:遗产)
.bind
答案 1 :(得分:0)
在Keyboard对象中没有名为highlightScales
的方法。我认为你的意思是this.highlightKeyboard
。
话虽如此 - bind()
用于将上下文传递给方法。它允许您手动设置this
,而不是使用该范围内的任何this
。