将函数作为事件处理程序的回调传递时,我的 javascript 项目中的值不正确

Getting incorrect values in my javascript project when passing function as callback on event handler

这里我刚刚提取了有问题的代码部分,因为它是一个带有 clickInfo 方法的对象,我想在单击 html 中的 testDivbtn 时使用它

var product = {
        jsondata:[
        {title:"GearBox", price:80000},
        {title:"Clutch", price:7000}
        ],
    loadInfo:function (event) {
    ​   // This line is printing first product info from the jsondata array​ - just to test
     console.log (this.jsondata[0].title + " " + this.jsondata[0].price);
      }
}

这很简单 div 附加到点击处理程序

$ ("#testDivbtn").click(product.loadInfo); 

这里是html

<div class="col-sm6"><button id="#testDivbtn" type="button" class="btn btn-default">Test Product</button></div>

它在控制台中显示错误 - 无法读取未定义的 属性“0” 我在我的应用程序的许多其他地方都遇到了这个错误,如果有任何一个指出错误,那将非常有帮助。

您需要使用bind

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

参考:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

最初当你使用this.jsondata[0].title时,这里的this指的是<button>元素,它没有属性 .jsondata

$(function() {
  var product = {
    jsondata: [{
      title: "GearBox",
      price: 80000
    }, {
      title: "Clutch",
      price: 7000
    }],
    loadInfo: function(event) {
      console.log(this.jsondata[0].title + " " + this.jsondata[0].price);
    }
  }
  $("#testDivbtn").click(product.loadInfo.bind(product));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-sm6">
  <button id="testDivbtn" type="button" class="btn btn-default">Test Product</button>
</div>

填充:

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          return fToBind.apply(this instanceof fNOP
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    if (this.prototype) {
      // Function.prototype don't have a prototype property
      fNOP.prototype = this.prototype; 
    }
    fBound.prototype = new fNOP();

    return fBound;
  };
}

There you need to understand few concept here related to use "this" object properly. few methods like bind() -(from ES5 onwards), apply() and call(). Now as I see your code will try to explain this in little detail

Here the button $(“#testDivbtn”) is an object on its own, and you are passing the product.loadInfo method to its click() method as a callback, as it is inside product.loadInfo method will no longer refer to the product object. "this" will now refer to the object where the product.loadInfo method is executed because this is defined in that method. And the object that is invoking product.loadInfo is the button object, product.loadInfo will be executed inside the button object’s click method.

即使您使用 product.loadInfo() 调用 loadInfo () 方法 在这一点上,很明显,当上下文发生变化时,当我们在对象最初定义的地方以外的某个其他对象上执行方法时,

the "this" keyword no longer refers to the original object where "this" was originally defined, but it now refers to the object that invokes the method where this was defined.

Solution to fix this when a method is passed as a callback function: Since you really want this.jsondata to refer to the jsondata property on the product object, we can use the Bind (), Apply (), or Call () method to specifically set the value of this.

如上回答建议使用绑定替换所有这样的地方

    $("#testDivbtn").click (product.loadInfo);

有了这个

    $("#testDivbtn").click (product.loadInfo.bind (product)); // it will print Gearbox 80000 in console.

我正在链接一个问题,这里非常适合查找有关应用调用绑定的更多详细信息 Javascript call() & apply() vs bind()?