JavaScript 构造函数 在同一构造函数中调用其他方法的方法

标签 javascript

我试图从同一构造函数中的另一个方法调用对象方法,但它似乎不起作用 - 我只是收到错误 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从内部(特别是引入 bindapplycall )。里面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/

相关文章:

javascript - 获取每个 tr 值并创建一个具有 td 值的对象

javascript - 使用正文解析器传递 zip 文件

javascript - 在页面末尾加载 jQuery?

javascript - 如何阻止 Google reCAPTCHA 显示警报?

javascript - 如何使用javascript从某些位置删除字符串并在该位置添加另一个字符串?

javascript - 在 passport.js 中带有 token 的验证电子邮件

javascript - 从多个回调 javaScript 返回最终对象

javascript - 如何获取url AngularJS的最后一部分

javascript - 用于 JavaScript 使用的 JSON API - 在服务器端或浏览器中处理 session 数据?

javascript - 如何按键将 JSON 对象转换为 Javascript 数组过滤器?