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

时间:2016-02-14 07:26:39

标签: javascript jquery json callback this

这里我刚刚提取了我有问题的代码部分,因为它是一个带有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” 我在我的应用程序的许多其他地方出现此错误,如果有任何一点错误,那将非常有帮助。

2 个答案:

答案 0 :(得分:1)

您需要使用bind

  

bind()方法创建一个新函数,在调用时,它具有它   此关键字设置为提供的值,具有给定的序列   调用新函数时提供的任何参数。

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

最初使用this.jsondata[0].title时,此处this引用<button>元素,该元素没有属性.jsondata

&#13;
&#13;
$(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));
})
&#13;
<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>
&#13;
&#13;
&#13;

<强>填充工具

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;
  };
}

答案 1 :(得分:0)

  

在这里你需要了解一些与正确使用“this”对象相关的概念。一些方法,如bind() - (从ES5开始),apply()和call()。   现在我看到你的代码了   试着解释一下这个细节

     
    

这里按钮$(“#testDivbtn”)本身就是一个对象,你将product.loadInfo方法作为回调传递给它的click()方法,因为它在product.loadInfo方法中将不再参考产品对象。 “this”现在将引用product.loadInfo所在的对象      执行方法,因为这是在该方法中定义的。      调用product.loadInfo的对象是按钮对象,product.loadInfo将在按钮对象的click方法中执行。

  

即使您使用product.loadInfo()调用loadInfo()方法 在这一点上,显而易见的是,当上下文发生变化时,当我们在某个其他对象上执行一个方法而不是最初定义该对象时,

  

“this”关键字不再引用最初定义“this”的原始对象,但它现在引用调用定义此方法的对象。

     
    

当方法作为回调函数传递时修复此问题的解决方案:     既然你真的希望this.jsondata引用产品对象的jsondata属性,我们可以使用Bind(),Apply()或Call()方法来专门设置它的值。

  

如上所述,建议使用bind替换所有这样的地方

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

用这个

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

我正在链接一个问题,这里寻找有关apply call bind的更多细节非常好 Javascript call() & apply() vs bind()?