开发者

Javascript Namespace Help

I have a pretty big Javascript script with loads of global variables & functions in it. Then a piece of code that calls one function from this js file: myfunc();

Ok, now I have cloned this script and modified some functionality, all function prototypes and variables are named the same in both scripts. So now I have two scripts loaded and one call to myfunc(), now we have a clash because there are loads of global variables with the same names and two myfunc()s.

What I want to do is wrap this cloned script in a namespace, so that I can modify the original call to: clone.myfunc() which will call the new function, but I also want myfunc() to jus开发者_如何学编程t refer to the original script. In other words I can't touch the original script (no permissions) and I want to be able to use both the clone and the original at runtime.

This is the script im cloning: http://pastebin.com/6KR5T3Ah

Javascript namespaces seem quite tricky this seems a nice namespace method:

var namespace = {
    foo: function() {
    }

    bar: function() {
    }
}

...

namespace.foo();
}

However that requires using an object, and the script (as posted above) is humongous at nearly 4000 lines, too much to objectize I think?

Anyone know a better solution to avoid namespace pollution, with one script I cant touch and one being a clone of that script. Just so I can call myfunc() and clone.myfunc() and all global variables will behave in their respected scope.

It's either that, or I go through and modify everything to have unique names, which may take a lifetime

This is a Mozilla addon if it helps context wise.

Thanks.


In general, you can avoid polluting the global namespace really easily. If you have code that looks like this:

var foo;

function bar() {
}

just wrap it in a function and immediately call the function:

(function() {
    var foo;

    function bar() {
    }
})();

Now foo and bar are constrained to that big anonymous function. They can still refer to each other with unqualified names, but they're no longer "global" properties (properties on the window object). This is sometimes called wrapping things up in a closure.

You can "export" things out of that closure in a few ways: 1. Return an object with function properties; 2. If you only need to export one function, just return the function reference; 3. Explicitly assign functions to window properties from within the closure:

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

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

The call would be to myNameSpace.myfunc().

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

    return myfunc;
})();

The call would be to myFuncReworked().

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

    window.myfunc = myfunc;
})();

The call would be to myfunc() (aka window.myfunc()).

All of this assumes that the script doesn't assume that its various global variables and functions will show up on the window object, of course.

This blog post may be useful in terms of background around the whole "wrapped in a closure" thing, although the thrust of the post is about avoiding anonymous functions (except scoping functions).


Edit Pointy points out (and that makes sense) that this is a plug-in, so if window isn't relevant, that third option can look like this instead:

// 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

That works because at global scope, this refers to the global object, which doesn't intrinsically have a "name;" passing it into the function lets us give it one easily. (In web pages, window refers to the global object, but actually window is just a property on the global object that it uses to refer to itself; the technical discussion of that gets...technical fairly quickly, so I'll leave it as I don't think it's hyper-relevant.)


It might work to do two things:

  1. Wrap everything in a function and
  2. Explicitly expose your "myfunc"

Add to the top of the file:

(function(global) {

and to the very end:

})(this);

And after you declare/define "myfunc" add:

global['myfunc'] = myfunc;

edit — @TJ explains the workings of this in his answer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜