2010-05-31 2 views
2

У меня есть довольно большой скрипт Javascript с множеством глобальных переменных. & функции в нем. Затем фрагмент кода, который вызывает одну функцию из этого js-файла: myfunc();Javascript Namespace Help

Итак, теперь я клонировал этот скрипт и модифицировал некоторые функции, все прототипы функций и переменные называются одинаковыми в обоих сценариях. Итак, теперь у меня два загруженных сценария и один вызов myfunc(), теперь у нас есть столкновение, потому что есть множество глобальных переменных с одинаковыми именами и двумя myfunc() s.

Что я хочу сделать, это обернуть этот клонированный скрипт в пространство имен, чтобы я мог изменить исходный вызов: clone.myfunc(), который вызовет новую функцию, но я также хочу, чтобы myfunc() просто ссылался к оригинальному сценарию. Другими словами, я не могу коснуться оригинального сценария (никаких разрешений), и я хочу иметь возможность использовать как клон, так и оригинал во время выполнения.

Это сценарий им Клонирование: 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() { 
    } 
})(); 

Теперь foo и bar ограничены в этой большой анонимной функции. Они все равно могут ссылаться друг на друга с неквалифицированными именами, но они больше не являются «глобальными» свойствами (свойствами объекта 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.myfunc()).

Все это предполагает, что сценарий предполагает, что его различные глобальные переменные и функции будут отображаться на объекте window, конечно.

This blog post может быть полезен с точки зрения фона вокруг всего, что «завернуто в закрытие», хотя толчок сообщения заключается в том, чтобы избежать анонимных функций (кроме функций обзора).


Edit Pointy указывает (и что имеет смысл), что это плагин, так что если 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 - это просто свойство на глобальном объекте, который он использует, чтобы ссылаться на себя, техническая дискуссия об этом быстро ... технически довольно быстро, поэтому я оставьте его, как я не думаю, что это гипер-отношение)

+0

Я думаю, что «окно» может не работать, если это плагин Mozilla, но я предполагаю, что передача этого «this» в функцию-оболочка будет работать и в этом контексте. Конечно, я ошибаюсь, поскольку я никогда не делал плагина. – Pointy

+0

Большое спасибо. Если я беру метод 1 выше, что происходит, когда анонимная функция вызывается сразу после ее объявления? Просто я не хочу ничего (функционально мудрый) исполнить, пока я не вызову myfunc() явно где-то еще в кодовой базе. Также, используя метод 1, я правильно понимаю, что могу включить столько функций и переменных, сколько хочу внутри этой пространства имен/анонимных функций, а затем просто экспортировать все, что мне нужно для публичного доступа? – Jason

+0

@Jason: Выполнение анонимной функции сразу же является тем же самым, что и отсутствие оболочки функций - создаются переменные, функции создаются, но не вызываются никакие функции, если только они не вызваны.:-) И да, вы можете включить столько функций там, сколько хотите. Библиотеки JavaScript часто используют эту идиому, чтобы они могли иметь множество частных внутренних функций и экспортировать только те, которые действительно нужны. –

1

это может работать, чтобы сделать две вещи:.

  1. Wrap все в функции и
  2. Явное подвергать «MyFunc»

Добавить в начало файла:

(function(global) { 

и до самого конца:

})(this); 

И после того, как вы заявляете/определить "MyFunc" добавить:

global['myfunc'] = myfunc; 

редактировать — @TJ объясняет работу этого в его ответе.