1

我正在学习 javascript 模块以及如何编写它们。我遇到了一个问题,即我不能 100% 确定我的模式是正确的。任何可能让我以后更容易的评论都会很好,但我的问题是我不确定如何正确使用原型。

我像这样使用我的模块:

        var cm = CodeMirror.fromTextArea(document.getElementById("code"), {
            lineNumbers: true,
            matchBrackets: true,
            mode: "text/x-csharp"
        });
        var adapt = new $.codeMirrorSignalRAdapter(cm, $.connection.codeHub);

但在我的adapter.prototype hubChange 中,this.silent 是未定义的。我想认为 var adapter = function(cm,hub) 是构造函数,我不知道如何从原型函数访问属性 self.[cm,hub,silent] 。

(function ($, window) {
    "use strict";

    if (typeof ($) !== "function") {
        // no jQuery!
        throw new Error("CodeMirrorAdapter: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file.");
    }
    if (typeof ($.signalR) !== "function") {
        throw new Error("CodeMirrorAdapter: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/hubs.");
    }

    var adapter = function (cm, hub) {
        var self = this;
        self.cm = cm;
        self.hub = hub;
        self.silent = false;

        cm.on("change", function (_, change) { self.onChange(change); });
        hub.client.Change = self.hubChange;

        return self;
    };

    adapter.fn = adapter.prototype = {
        init: function (cm, hub) {

        },
        onChange: function (change) {
            if (!this.silent) {
                this.hub.server.change(change)
                        .done(function () { })
                        .fail(function (ee) { alert(ee) });
            }
        },
        hubChange: function (change) {
            alert(this.silent);
            this.silent = true;
            this.cm.replaceRange(change.text[0], change.from);
            this.silent = false;
        },
    };


    $.codeMirrorSignalRAdapter = adapter;
}(window.jQuery, window));

除了这个关键字的问题之外,模块设计看起来还不错吗?

4

1 回答 1

1

的值this可以是 5 个可能选项中的任何一个。阅读 MDN 上的这篇文章以获取更多信息:https ://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this

在您的特定情况下hub.client.Change = self.hubChange;,您正在注册hubChange为处理程序。问题是当处理程序被调用时,没有代码可以确保this已设置为正确的适配器对象。

我们如何确保这一点?

hub.client.Change = function () { self.hubChange.apply(self, arguments);};

apply你可以在这里阅读更多关于https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

我们所做的与您对cm.on("change")绑定所做的类似。

对代码的思考

您的构造函数以return self;不需要的结尾。当函数作为构造函数调用时,即使用new关键字,它将隐式返回一个新实例。当函数在没有new关键字的情况下被调用时,它将返回函数返回的任何内容,在这种情况下,它不会是一个新实例。这将是任何this设置。它很可能会返回window。建议,删除该行。这样,如果您不小心在没有 new 的情况下调用它,您将返回 undefined。

于 2012-12-01T22:06:34.543 回答