2010-05-31 62 views
2

我有一個非常大的Javascript腳本,其中包含全局變量負載&函數。然後從這個js文件中調用一個函數的一段代碼:myfunc();好吧,現在我已經克隆了這個腳本並修改了一些功能,所有的函數原型和變量在兩個腳本中都被命名爲相同。所以現在我有兩個腳本加載和一個調用myfunc(),現在我們有一個衝突,因爲有大量的全局變量具有相同的名稱和兩個myfunc()。Javascript名字空間幫助

我想要做的就是將這個克隆的腳本包裝在命名空間中,以便我可以將原始調用修改爲:clone.myfunc(),它將調用新函數,但我也希望myfunc()到原來的腳本。換句話說,我無法觸及原始腳本(無權限),我希望能夠在運行時使用克隆和原始文件。

這是腳本IM克隆:http://pastebin.com/6KR5T3Ah

的Javascript命名空間顯得相當棘手這似乎是一個很好的命名方法:

var namespace = { 
    foo: function() { 
    } 

    bar: function() { 
    } 
} 

... 

namespace.foo(); 
} 

然而,需要使用一個對象,並且腳本(如上面貼)在近4000條線路上是巨大的,我認爲太過於客觀化了?

任何人都知道一個更好的解決方案,以避免命名空間污染,一個腳本我不能碰,一個是該腳本的克隆。所以我可以調用myfunc()和clone.myfunc(),並且所有全局變量都將在其受尊重的範圍內運行。

它要麼,我經過和修改一切有唯一的名字,這可能需要一輩子

這是一個Mozilla插件如果有幫助的上下文明智的。

謝謝。

回答

6

通常,您可以很容易地避免污染全局名稱空間。如果你有一些代碼看起來是這樣的:

var foo; 

function bar() { 
} 

只是包裝在一個函數,並立即調用該函數:

(function() { 
    var foo; 

    function bar() { 
    } 
})(); 

現在foobar被限制到大的匿名函數。他們仍然可以使用非限定名稱互相引用,但它們不再是「全局」屬性(window對象上的屬性)。這有時被稱爲封閉事物。

您可以通過幾種方式將事件從閉包中「導出」:1.返回具有函數屬性的對象; 2.如果您只需要導出一個函數,只需返回函數引用; 3.顯式地從封閉件內將功能分配給window屬性:

// 1. Returning an object with function properties: 
var myNamespace = (function() { 
    function myfunc() { 
     // ... 
    } 

    return { 
     myfunc: myfunc 
    }; 
})(); 

呼叫將myNameSpace.myfunc()

// 2. Returning just one function 
var myFuncReworked = (function() { 
    function myfunc() { 
     // ... 
    } 

    return myfunc; 
})(); 

該電話將是myFuncReworked()

// 3. Explicitly assign to `window` property: 
(function() { 
    function myfunc() { 
     // ... 
    } 

    window.myfunc = myfunc; 
})(); 

的通話將myfunc()(又名)。

所有這些假定腳本不假定假設當然,它的各種全局變量和函數將顯示在window對象上。

This blog post可能在圍繞整個「封閉」事物背景方面很有用,儘管這篇文章的主旨是避免匿名函數(除了範圍函數)。


編輯尖尖指出(和有意義),這是一個插件,所以如果window是不相關的,即第三個選擇可以是這樣的,而不是:

// 3. Explicitly assign to global property: 
(function(global) {   <== Note the new argument 
    function myfunc() { 
     // ... 
    } 

    global.myfunc = myfunc; <== Use the new arg instead of `window` 
})(this);      <== Pass `this` into the function 

因爲在全局範圍內,this引用全局對象,它本質上沒有「名稱」將它傳遞給函數可以讓我們輕鬆地給它一個。 (在網頁中,window指的是全局對象,但實際上window僅僅是的一個屬性它用來引用自身的全局對象;技術上的討論非常快速,所以我會離開它,因爲我不認爲它的Hyper-相關)

+0

我認爲如果是「Mozilla插件」,「窗口」可能不起作用,但我認爲將「this」傳遞給包裝函數也適用於該上下文。我當然可能會錯,因爲我從來沒有做過插件。 – Pointy 2010-05-31 21:26:37

+0

非常感謝。如果我採用上面的方法1,當匿名函數在聲明後立即被調用時會發生什麼?只是我不需要任何東西(功能明智)執行,直到我明確地調用myfunc()在代碼庫中的其他地方。 另外,使用方法1,我是否認爲我可以在該命名空間/匿名函數中包含儘可能多的函數和變量,然後只需要導出任何我需要公開的函數? – Jason 2010-05-31 21:31:07

+0

@Jason:立即執行匿名函數基本上與沒有函數包裝器一樣 - 變量被創建,函數被創建,但是除非被調用,否則不會調用函數。:-)是的,你可以在其中包含儘可能多的功能。 JavaScript庫經常使用這種習慣用法,因此它們可以擁有許多私有的內部函數,並且只導出真正需要的內部函數。 – 2010-05-31 21:36:36

1

它可能工作做兩件事情:

  1. 裹一切功能和
  2. 明確暴露你的「MYFUNC」

添加到文件的頂部:

(function(global) { 

,並盡頭:

})(this); 

你申報/定義 「MYFUNC」 添加後:

global['myfunc'] = myfunc; 

編輯 — @TJ在他的回答中解釋了這一點。