JS:在同一对象内调用对象内部的函数

时间:2014-11-04 03:53:38

标签: javascript function

所以,我有这个:

var listener = {
    _handleMessage: function(b) {
        var c = b.data;
        if (c) this.{c}; //this not works
    },
    testFunc: function() {
        console.log("success");
    }
    startListen: function() {
        window.addEventListener("message", this._handleMessage, !1)
    }
};

listener.startListen();

预期结果:当数据通过startListen时,它会将数据传递给_handleMessage。从那里,它检查数据以调用监听器内的函数(例如,如果testFuncb.data,则将调用testFunc)。

使用像我发布的内容不起作用。使用this[c]();无效(this[c] is not a function)。还有其他解决方案吗?

解决

找到一种更优雅的方式:

_handleMessage: function(b) {
        var c = b.data;
        if (c) {
            var d = listener[c.action];
            d && "function" == typeof d (function() {
                d.call(listener, c.params || {});
            });
        }
    },

3 个答案:

答案 0 :(得分:2)

你在哪里:

window.addEventListener("message", this._handleMessage, !1);

_handleMessage 函数传递给元素处理程序。当处理程序调用时,它的 this 被设置为其处理程序调用函数的元素,而不是 listener 对象。您可以按照StriplingWarrior的说明修复它,或者您可以执行以下操作:

window.addEventListener("message", function(){listener._handleMessage()}, false)

以便将 _handleMessage 中的 设置为您期望的对象(即 listener )。

修改

在“已解决”的代码中:

        d && "function" == typeof d (function() {
            d.call(listener, c.params || {});
        });

只要 d 解析为真值,那么分组运算符中的函数始终评估,typeof d返回的内容无关紧要,所以你有效地拥有:

        d && d.call(listener, c.params || {});

这样:

    if (c) {
        var d = listener[c.action];
        d && "function" == typeof d (function() {
            d.call(listener, c.params || {});
        });
    }

也可能是:

    if (c && listener[c.action]) {
        listener[c.action](c.params || {});
    }

答案 1 :(得分:1)

这已被多次询问和回答。您需要指定this._handleMessage.bind(this),以便_handleMessage具有上下文(this)。虽然有些人可能会说使用function(b) { self._handleMessage(b); })作为其他答案,但这可能更为简洁。

精确相同的逻辑适用于您将类方法作为回调传递的任何情况,例如setTimeout

以上是最简单的,但还有其他方法。如果您需要在多个位置使用_handleMessage的绑定版本,则预绑定它可能很有用:

listener._handleMessage = listener._handleMessage.bind(listener);

或者,你可以使用下划线的_.bindAll

_.bindAll(listener, '_handleMessage');

或者,您可以在对象内的init函数中执行此操作:

var listener = {
    _handleMessage: function(b) {
        var c = b.data;
        if (c) this.{c}; //this not works
    },
    startListen: function() {
        window.addEventListener("message", this._handleMessage, !1)
    },
    init: function() {
        this._handleMessage = this._handleMessage.bind(this);
        return this;
    }
}.init();

如果您在ES6环境中工作,胖箭头功能可以通过defining this lexically解决此问题,所以您可以这样做

window.addEventListener("message", b => this._handleMessage(b), !1);

在这种情况下,this不是事件机制(通常是全局对象)调用函数的上下文的值,而是周围的this,这是什么你想要的。

至于this.{c},不知道你在那里做什么。

答案 2 :(得分:0)

请记住,JavaScript中的this是指在运行时调用该函数的上下文。当“message”事件触发时,您的listener对象的上下文中不会调用您的事件侦听器。

尝试创建一个匿名函数作为处理程序,并确保它在正确的上下文中调用事件,如下所示:

var listener = {
    _handleMessage: function(b) {
        var c = b.data;
        if (c) this.{c}; //this not works
    },
    testFunc: function() {
        console.log("success");
    }
    startListen: function() {
        var t = this; // capture "this" when `listener.startListen()` is invoked.
        window.addEventListener("message", function(b) {t._handleMessage(b);}, !1)
    }
};

listener.startListen();