【问题标题】:How to pass 'this' object to callback function which is called in a function using protocol apply如何将“this”对象传递给使用协议应用的函数中调用的回调函数
【发布时间】:2017-02-26 14:54:20
【问题描述】:

main 函数如下,会导致 'setState' is not a valid property 异常。

componentWillMount = function () {
    api.daysOfMonth(this, this.props.month, this.props.year, function (ds) {
        var days = [];
        ds.forEach(function (jsonDay) {
            var day =  {date: jsonDay.date, inRange: jsonDay.inRange};
            days.push(day);
        });

        this.setState({ daysOfMonth: days });
  });

api.js 的 sn-p 如下。 主函数调用 Api.daysOfMonth(...),Api.daysOfMonth 将使用全局对象调用 ajax 方法并使用协议 apply 调用回调函数,回调函数从 main 函数传入如上脚本。

ApiImpl = (function () {
                function ApiImpl() { }
                
                ApiImpl.prototype.invoke = function (callerObj, callback, action) {
                    var params = [];
                    for (var _i = 3; _i < arguments.length; _i++) {
                        params[_i - 3] = arguments[_i];
                    }

                    params.push(callback); //push callback function into params, so object of QWebChannel can callback the function after execute the 'action'
                    
                    if (typeof window['api'] === 'undefined') {
                        new QWebChannel(qt.webChannelTransport, function (channel) {
                            window['api'] = channel.objects.api;
                           
                            var func = window['api'][action].bind(callerObj); 
                            return func.apply(callerObj, params); //here goes error
                        });
                    }
                    
                    var func = window['api'][action].bind(callerObj);
                    return func.apply(callerObj, params); //here goes error
                };
                return ApiImpl;
            }());
            Api = (function () {
                function Api() {
                }
                Api.daysOfMonth = function (callerObj, month, year, callback) {
                    this.impl.invoke(callerObj, callback, 'daysOfMonth', month, year);
                };
                return Api;
            }());
            Api.impl = new ApiImpl();
            exports_1("Api", Api);

【问题讨论】:

  • 您希望this 成为什么? jsonDay?

标签: javascript callback this


【解决方案1】:

如果这确实回答了您的问题,原因是因为 .bind() 将新创建的函数的 this 绑定到您作为第一个参数传递的函数。

componentWillMount = function () {
    api.daysOfMonth(this, this.props.month, this.props.year, function (ds) {
        var days = [];
        ds.forEach(function (jsonDay) {
            var day =  {date: jsonDay.date, inRange: jsonDay.inRange};
            days.push(day);
        });

        this.setState({ daysOfMonth: days });
  }.bind(this));

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

注意,如果你写的是 es6,你可以使用箭头函数来做同样的事情。

componentWillMount = function () {
    api.daysOfMonth(this, this.props.month, this.props.year, (ds) => {
        var days = [];
        ds.forEach(function (jsonDay) {
            var day =  {date: jsonDay.date, inRange: jsonDay.inRange};
            days.push(day);
        });

        this.setState({ daysOfMonth: days });
  });

简而言之,箭头函数中的this 是词法范围,这意味着this 保证与定义箭头函数的this 相同。

另见:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

【讨论】:

  • 是的,您的解决方案正常!我把 bind() 放在内部函数中,我应该把它放在我的 main 函数中。非常感谢。
猜你喜欢
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 1970-01-01
相关资源
最近更新 更多