将窗口对象传递到Javascript命名空间中

Passing a window object into Javascript namespace

本文关键字:Javascript 命名空间 窗口 对象      更新时间:2023-09-26

我试图更好地理解javascript中的名称空间,并找到了一个javascript立即调用函数表达式的例子,该表达式将窗口对象作为参数。这是它的代码:

var CG = CG || {};
CG.main = (function(window) {
    var FOCAL_LENGTH = 8.0;
    var context, width, height, startTime;
    var init = function() {
        var element = document.getElementById("canvas1");
        context = element.getContext("2d");
        width = element.width;
        height = element.height;
        startTime = (new Date()).getTime() / 1000.0;
        tick();
    }
var original_onload = window.onload || function() {};
    window.onload = function() {
        original_onload();
        CG.main.init();
    }
    return {
        init: init,
        draw: draw_shape,
        clear: clear_canvas
    };
}(window));

在名称空间定义的末尾,有一行括号中有window,我对它的功能感到困惑。我认为将window的参数添加到定义末尾的目的是将全局窗口变量绑定到命名空间,然后命名空间将向窗口添加不同的属性,但我真的不能确定。

在另一个例子中,有一个随机变量名称被传递到命名空间的定义中,在命名空间定义的末尾,命名空间的实际名称被作为参数传递:

var namespace = namespace || {};
// here a namespace object is passed as a function
// parameter, where we assign public methods and
// properties to it
(function( o ){
    o.foo = "foo";
    o.bar = function(){
        return "bar";
    };
})(namespace);
console.log(namespace);

所以这里确实有几个问题:

  1. 在命名空间定义的末尾传递参数的功能是什么?

  2. 如果我对这一切的直觉是不正确的,那么这种名称空间创建javascript的一般结构是什么?

很明显,我对这件事很陌生,所以任何帮助都将不胜感激,谢谢。

我会尽力解释这一点,但我对它的理解来自Kyle Simpson。他太棒了,你应该去看看他-D

您正在询问一个关于立即调用函数表达式(IIFE)的问题,向它们传递参数,以及为什么有人会这样做。

首先,在这种情况下使用IIFE的原因是为了限制变量的范围。

这一点很重要,因为随着程序变得越来越大,添加了许多部分,您很容易在一个变量与另一个变量之间发生冲突。

app.js可能有

variable = "thing";

不久之后,Gelse.js可能会出现

variable = "not thing";

这是一个巨大的问题。在javascript中,可以通过创建立即运行并运行一次的"模块"或函数来避免这种情况。

这样,您在函数中创建的变量和方法就不会"污染全局范围/命名空间"

但是,如果您需要或希望全局窗口对象上有可用的内容,该怎么办?

好吧,您可以将它添加到"窗口"中,这是javascript中的全局范围。

(function Module(window){
   var _thing = "private thing that only exists in this function";
   window.thing = _thing;
      //IS NOW AVAILABLE GLOBALLY AND EXPLICITLY ON WINDOW OBJECT
      //window.onload you can wait for DOM/page before running the rest
})(window);

你也可以在你的函数中随意命名它:

(function niftyModule(global){
    global.variable = "nifty text!";
})(window)

当您使用多个库时,这一点变得尤为重要。

出于某种原因,每个人都喜欢使用"$"作为他们库的表示,这样你就可以访问他们的私有方法(它们实际上也只是IIFE中的函数!(这是一种非常流行的构建好东西的方法)。

那么,如果您正在使用jQuery和另外两个同样使用$访问其公共方法/api的库,该怎么办??

很简单,您可以通过将函数/模块范围内的变量作为参数传入,来指定要指定的变量!

(function NiftyModule(window, $){
 //Now, every time you use $ in here it means jQuery and not something else!
})(window, jQuery);

重要的是要充分考虑功能和范围。以不同的方式构建一些变量。

例如,is…

var text = "nifty text";

与相同

text = "nifty text";

如果你在函数内部做同样的事情呢?这两个版本有何不同?

此外,要习惯于在IIFE中构建自己的程序,并适当地限制您正在编写的代码的范围。

您还可以从函数中返回对象,这些函数具有要全局访问的方法和变量,而无需将它们添加到窗口对象中。

一开始它很复杂,但将来它会为你省去很多麻烦和bug!

最后,在你的例子中:

//initialize a global variable called namespace. If this already
//existed then assign it the previous values. If not, make it an empty
//object.
var namespace = namespace || {};
//pass namespace into an IIFE. Within the IIFE refer to namespace as "o"
(function( o ){
    //assign a variable to namespace
    o.foo = "foo";
    //assign a method to namespace
    o.bar = function(){
        return "bar";
};
})(namespace);
//now when you log namespace it will have those properties.
console.log(namespace);