2012-03-19 67 views
7

我不是一个很好的JavaScript用户,但我可以用它完成任务。我对我用JavaScript编写的代码并不感到自豪,所以我决定改变它。这是我的第一步:JavaScript中良好范围的方法

我想为一个项目创建我自己的库,下面是最初的结构。

window.fooLib = {}; 

(function (foo) { 
    "use strict"; 

    foo.doSomeStuff = function(param1) { 

     console.log(new AccommProperty(param1)); 
    } 

    //some internal function 
    function AccommProperty(nameValue) { 
     var _self = this; 
     _self.name = nameValue; 
    } 

}(fooLib)); 

我以前立即调用的函数表达式这里来初始化我的变量。在这种情况下,它是fooLib

我不知道我是否应该做一些其他的事情,使window.fooLib更安全。我的意思是,如果我正确理解JavaScript,它可以被代码运行后的任何其他代码覆盖。

你的想法是什么?

+0

使用“use strict”;并保护你的对象,这就是你所能做的。 – Christoph 2012-03-19 09:03:40

+0

@Christoph我使用'“严格使用;”',如你所见。这是使用它的正确方式和地点吗? – tugberk 2012-03-19 09:05:52

+2

是的。 [见john resig的文章](http://ejohn.org/blog/ecmascript-5-objects-and-properties/)关于如何实现保护或者https:// developer上的Object.freeze(obj) .mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze – Christoph 2012-03-19 09:20:51

回答

1

如果要防止覆盖变量,可以使用Object.defineProperty(),其中可写:false,可配置:false。在你的情况下:

(function() { 
    "use strict"; 
    var foo = {}; 
    //some internal function 
    function AccommProperty(nameValue) { 
     var _self = this; 
     _self.name = nameValue; 
    } 
    foo.doSomeStuff = function(param1) { 

     console.log(new AccommProperty(param1)); 
    } 
    Object.defineProperty(window, "foolib", {value:foo}); 
}()); 

不过,这没有什么好的理由。它需要EcamScript 5.1才能工作,并且没有垫片;也许可以用getters/setter来防止覆盖=运营商。

但是,也不应该让你的图书馆不可覆盖。只是不要使用覆盖lib的代码。或者,也许有人甚至想用另一个更好的lib用相同的接口覆盖你的函数?

如果问题是关于要共享的库,可能与其他名称空间冲突,则可以查看jQuery.noConflict

0

每个JavaScript对象都可以被重写。这是JavaScript的本质,不可能改变它。所以你不能在这个意义上使你的代码安全。

至于selfinvoked功能:你应该使用它们,当你想有局部变量,但viisible所有的功能。所以在你的情况下AccommProperty是这样的变量。在范围内定义doSomeStuff不会产生任何影响,除非doSomeStuff将使用范围内定义的变量。

所以当你想隐藏用户的变量和/或你需要全局变量而且你害怕名称冲突使用selfinvoked函数。

+0

谢谢!改变了我的示例代码。我认为现在更有意义。 – tugberk 2012-03-19 08:57:20

-1

我不知道我是否应该做一些其他的事情,使window.fooLib更安全。我的意思是,如果我正确理解JavaScript,它可以被代码运行后的任何其他代码覆盖。

您可以尝试使window.fooLib为局部变量。使用closures and nested functions一个可以模拟一个命名空间,你可以把你所有的数据,而不是将其放入全局范围或将其连接到window对象:

(function() { 

    // all functions nested in foo() have access to fooLib. 
    fooLib = {} 

    fooLib.doSomeStuff = function(param1) { 
     console.log(param1); 
     console.log(fooLib); 
    } 

    //some internal function 
    function AccommProperty() { 
     console.log(fooLib); 
    } 

}()); 

详情请参阅Javascript Closures: Encapsulating Related Functionality

+0

好的,但在这种情况下,我不能在这个IIFE之外使用'fooLib',如果我想创建一个库,这没什么意义。或者我错了? – tugberk 2012-03-19 08:59:20

+0

你的fooLib也被连接到了窗口中......并且你需要它来提供外部访问(这是库的意义?!)如果你不工作,你创建的任何对象(ES3)都可以被覆盖与ES5并保护它。 – Christoph 2012-03-19 09:00:54

+0

@tugberk:将整个库放在一个函数中,该函数将库状态保存为局部变量。您的所有库函数都成为嵌套函数。 – 2012-03-19 09:06:14