Object.Prototype方法和IIFE中的“使用严格”(立即调用的函数表达式)

时间:2012-06-29 02:50:50

标签: javascript inheritance anonymous-function iife

原始代码:

'use strict';
function GitJs(config) {
    var defaults = {
        inheriting: false,
        clientId: undefined,
        accessToken: undefined,
        baseUrl: 'https://api.github.com',
        mode: 'read'
    };

    this.config = $.extend(defaults, config);
}

/**
 * Gets the jQuery method that GitJs#generateApiRequest is going to use to send the ajax request.
 *
 * @param {string} httpVerb The HTTP verb that the request will use,
 * @return string
 */
GitJs.prototype.getCommandMethod = function (httpVerb) {
    var method = $.get;

    switch (httpVerb) {
    case 'GET':
        method = $.get;
        break;
    case 'POST':
        method = $.post;
        break;
    }
    return method;
};

...

新代码:

(function() {
'use strict';
    'use strict';
    function GitJs(config) {
        var defaults = {
            inheriting: false,
            clientId: undefined,
            accessToken: undefined,
            baseUrl: 'https://api.github.com',
            mode: 'read'
        };

        this.config = $.extend(defaults, config);
    }

    /**
     * Gets the jQuery method that GitJs#generateApiRequest is going to use to send the ajax request.
     *
     * @param {string} httpVerb The HTTP verb that the request will use,
     * @return string
     */
    GitJs.prototype.getCommandMethod = function (httpVerb) {
        var method = $.get;

        switch (httpVerb) {
        case 'GET':
            method = $.get;
            break;
        case 'POST':
            method = $.post;
            break;
        }
        return method;
    };

    ...
}());

正如这段代码所示,当我尝试时:

var gitjs = new GitJs();

我被告知GitJs未定义

我到底在想什么:

  • 我不想将use strict放在每个方法中。
  • 如果我的代码被缩小并连接到另一个文件,我希望我的代码能够很好地发挥作用。
  • 我希望稍后使用.prototype语法来简化继承(以及代码清晰度)
  • 我不想制作全局var gitJs变量,因为它可能会被其他人的脚本覆盖。
  • 我假设用户将始终通过new关键字
  • 调用对象构造函数

为了记录,我知道我错了。方式错了。我似乎无法弄清楚我思想中的缺陷在哪里,我会喜欢一些指导。

3 个答案:

答案 0 :(得分:4)

你的问题是GitJS现在是立即调用函数的私有变量。您无法在私有范围内隐藏您的功能,并且可以同时公开使用它。它们是相互排斥的目标。

因此,您需要通过窗口

明确设置全局变量
var GitJS;
(function() {
    'use strict';
     GitJS = function(){ ... }
     ...
}());

或从IIFE内部返回导出的函数。

var ExportedGitJS = (function(){ //using a different name just to be clear...
    'use strict';
    var GitJS = function(){ ... }
    ...
    return GitJS;
}());

好吧,我骗了。您可以制作Javascript模块而不必依赖全局变量,但通常也意味着使用不同的模块创建约定和/或使用模块库。如果您对此感兴趣,我强烈建议您查看http://requirejs.org/

答案 1 :(得分:2)

@missingno是正确的,但我必须补充一点,您只需使用RequireJSequivalent loader一步即可。你对全局变量持怀疑态度;如果你承诺在具有已定义依赖项的异步模块中运行所有JavaScript,那么你可以简单地将你的GitJs构造函数返回到全局定义函数,然后在需要它的任何东西中需要你的GitJS模块。

// using the global define function provided by an AMD loader
// assuming that jQuery has already been provided by the paths config
define(['jquery'],function($) {
    'use strict';
    var GitJS = function() { ... }
    return GitJS
});

答案 2 :(得分:2)

关于提供一些指导,我不确定这听起来是否完全明显,但方法:

  • 不在每个方法中插入use strict pragma
  • 连接时不对其他来源施加严格模式
  • 使用.prototype语法
  • 不需要全局var gitJs变量
  • 让用户通过new关键字
  • 调用对象构造函数

它是:

/* Class constructor, public, globally available */
function GitJs(config) {
    'use strict'; /* You may want to drop this one */
    var defaults = {
        inheriting: false,
        clientId: undefined,
        accessToken: undefined,
        baseUrl: 'https://api.github.com',
        mode: 'read'
    };

    this.config = $.extend(defaults, config);
}

/* IIFE to wrap the *main* strict pragma */
(function () {
    'use strict';

    GitJs.prototype.getCommandMethod = function (httpVerb) {
        /* ... */
    };

    GitJs.prototype.someOtherMethod = function (someParam) {
        /* ... */
    };

})();

...

/* some other block */
... {
    var gitjs = new GitJs();
};

这是否部分回应了这个问题?