我试图从同一构造函数中的另一个方法调用对象方法,但它似乎不起作用 - 我只是收到错误 TypeError: undefined is not a function (evaluating 'this.uiDisplayOptions()')
.
我正在使用 new
实例化该对象关键字var ui = new _ui()
.
有人知道为什么它不起作用吗?我见过建议这种设置的示例。
代码如下:
function _ui() {
this.uiDisplayOptions = function() {
var len = channels[currentChannel].stepsChannel;
$("select#length option")
.prop('selected', false)
.filter('[value="' + len + '"]')
.prop('selected', true);
var rand = channels[currentChannel].randomAmtChannel;
$("select#randomness option")
.prop('selected', false)
.filter('[value="' + rand + '"]')
.prop('selected', true);
var dir = channels[currentChannel].readDirection;
$("select#readdirection option")
.prop('selected', false)
.filter('[value="' + dir + '"]')
.prop('selected', true);
}
this.uiSetListeners = function() {
// Select Channel
$("#selectChannel0").addClass("green");
$(".channelselect").click(function() {
$(".channelselect").removeClass("green");
$(this).addClass("green");
currentChannel = $(this).data("channel");
displayUpdateChannel();
this.uiDisplayOptions();
});
// Select Row
$("#selectRow0").addClass("red");
$("#selectRow0").click(function() {
currentRow = 0;
$("#selectRow1").removeClass("red");
$(this).addClass("red");
});
$("#selectRow1").click(function() {
currentRow = 1;
$("#selectRow0").removeClass("red");
$(this).addClass("red");
});
// Increment/Decrement Selected Row Pattern
$("#patternInc").click(function() {
selectPatternRow(1);
displayPattern();
});
$("#patternDec").click(function() {
selectPatternRow(-1);
displayPattern();
});
// Shift Left/Right Selected Row Pattern
$("#shiftLeft").click(function() {
selectShiftRow(-1);
displayPattern();
});
$("#shiftRight").click(function() {
selectShiftRow(1);
displayPattern();
});
// Handle Row 'Pattern Locks'
$(".lock").click(function() {
var step = $(this).data("lockstep");
switch(toggleLockBit(step)) {
case 0:
$(this).removeClass("red green");
break;
case 1:
$(this).addClass("red");
break;
case 2:
$(this).removeClass("red").addClass("green");
break;
}
displayPattern();
});
// Handle Channel Length change
$("#length").change(function() {
selectCurrentChannelLength($(this).val());
displayChannelLength();
});
// Handle Channel Randomness change
$("#randomness").change(function() {
selectCurrentChannelRandomAmt($(this).val());
displayRandomAmt();
});
}
}
最佳答案
this.uiSetListeners = function() {
// Select Channel
$("#selectChannel0").addClass("green");
$(".channelselect").click(function() {
$(".channelselect").removeClass("green");
// this here does not refer to the this of the object being created.
// it refers to the anonymous function being created in the click call.
// jQuery is probably invoking this and binding this to undefined,
// but even if it wasn't then this code would behave incorrectly.
$(this).addClass("green");
currentChannel = $(this).data("channel");
displayUpdateChannel();
this.uiDisplayOptions();
});
});
当在函数内部时 this
的值可能会改变。它有自己的绑定(bind),称为 ThisContext,并且不能保证指向您正在调用的对象 this
从内部(特别是引入 bind
、 apply
和 call
)。里面uiSetListeners
, this
通常绑定(bind)到函数(假设您正确调用构造函数,并且不使用任何 bind
魔法,函数又绑定(bind)到对象)。
但是在你的 click
里面,处理程序,您将函数委托(delegate)给 jQuery。 jQuery 不知道您的对象,因此它不会绑定(bind) this
(或将其绑定(bind)到 undefined
),并且默认情况下它不与对象关联(因为该函数是匿名声明的并且未绑定(bind)到对象)。换句话说,您的click
处理程序指向不同的 this
比你的this.uiSetListeners
声明是。
解决这个问题的方法是使用 var that = this;
一种机制。如果您采用这种方法,您可能应该定义 var that = this
在构造函数的顶部(以便其他人可以看到发生了什么)并替换 this
的任何发生率构造函数内部带有 that
。
这可以确保其他用户使用 call
调用您的构造函数。 , bind
等,该对象将正确绑定(bind)到提供的 this
.
var that = this;
that.uiSetListeners = function() {
// Select Channel
$("#selectChannel0").addClass("green");
$(".channelselect").click(function() {
$(".channelselect").removeClass("green");
$(this).addClass("green");
currentChannel = $(that).data("channel");
displayUpdateChannel();
that.uiDisplayOptions();
});
});
请注意,ES6 使用粗箭头表示法修复了此问题。
this.uiSetListeners = function() {
// Select Channel
$("#selectChannel0").addClass("green");
$(".channelselect").click(() => {
$(".channelselect").removeClass("green");
$(this).addClass("green");
currentChannel = $(this).data("channel");
displayUpdateChannel();
this.uiDisplayOptions();
});
});
只要您记得注意 this
,您就应该完全能够从构造函数中调用其他方法。 .
通常最好使用 YourConstructor.prototype.methodName
相反,因为这首先会减少嵌套,但也会使用原型(prototype)链。将功能分配给 this
在构造函数中不会将它们分配给原型(prototype)链,这也意味着每次创建新对象时都会重新创建它们。您只需将函数分配给 this
如果它们的实现依赖于传递给构造函数的值,并且在构造函数中捕获这些值作为创建对象的状态是不合适的,则在构造函数内部。
关于JavaScript 构造函数 在同一构造函数中调用其他方法的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30012037/