Isolating External Javascript from defining methods in the global (window) scope
我需要在我的网站上包含一个由第三方编写的对javascript的引用。遗憾的是,编写此脚本的开发人员决定全局定义其所有函数。你知道,就像这样:
1 2 3 4 5 6 7 | function AwesomeStringHelper() { // ... } function MyGreatFunction() { // ... } |
当我使用
由于我更喜欢不污染全局范围,有没有方法可以更改外部脚本的范围?理想情况下,我希望能够引用类似于
首先,尝试教育第三方开发人员如何正确编写模块。
如果不起作用,请执行以下操作:
1 | var ExternalLibrary = ExternalLibrary || window; |
在代码的顶部。
然后,您可以通过使用
或者,在
预加载:
1 | var ExternalLibrary = { _current: Object.keys(window) }; |
后负荷:
1 2 3 4 5 6 7 | Object.keys(window).forEach(function(key) { if (ExternalLibrary._current.indexOf(key) < 0) { ExternalLibrary[key] = window[key]; delete window[key]; } }); delete ExternalLibrary._current; |
我在过去使用过类似的方法(在使用严格模式之前)来检查泄漏的全局变量。
如果您的第三方模块直接分配给
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | function wrapModule(code) { // create a"fake" window object that inherits from the global object var fakeWindow = Object.create(window); // create a function wrapping the code // note that"window" is a parameter name in this function, shadowing // the global object var func = Function("window", code); // call function func.call(fakeWindow, fakeWindow); // return fake window object return fakeWindow; } // run code const fakeWindow = wrapModule(` var x = 0; // local variable (will not be exported) y = 1; // global variable (will still be leaked) window.z = 2; // assignment to window this.w = 3; // assignment to this `); // check what variables are exposed console.log('window.x', typeof x); // window.x undefined console.log('window.y', typeof y); // window.y number console.log('window.z', typeof z); // window.z undefined console.log('window.w', typeof w); // window.w undefined // check what variables are exposed in fakeWindow console.log('fakeWindow.x', typeof fakeWindow.x); // fakeWindow.x undefined console.log('fakeWindow.y', typeof fakeWindow.y); // fakeWindow.y number console.log('fakeWindow.z', typeof fakeWindow.z); // fakeWindow.z number console.log('fakeWindow.w', typeof fakeWindow.w); // fakeWindow.w number |
假设您知道正在定义的特定函数,那么在加载脚本之后,这将不起作用吗?
1 2 3 4 5 | const ThirdPartyLib = {AwesomeStringHelper, MyGreatFunction}; delete window.AwesomeStringHelper; delete window.MyGreatFunction; ThirdPartyLib.AwesomeStringHelper(haveFun); |
不确定jquery是否是一个选项,或者您是否关心它,但我不知道如何编写本机JS Ajax调用,请放心:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | $(document).ready(function(){ $.ajax({ url: 'www.example.com/awesome_script.js', // get the contents of the external script type: 'GET', crossDomain: true, dataType: 'html', success: function(data){ // build our script tag and wrap the contents inside of a function call var script ="" script+="var callMe = function(call_func, var1, var2, var3){"; script+= data; script+="return typeof call_func === 'function' ? call_func(var1, var2, var3) : 'You trying to dynamically call a variable? idk how to do that.';"; script+="};"; script+="<\/script>"; // assuming this is legal then just append the custom script tag to the <body> :-) $('body').append($(script)[0]); // profit? callMe('AwesomeStringHelper', 'some_var'); // this function accepts one parameter callMe('MyGreatFunction'); // this function accepts no parameters } }); }); |
您可以将整个脚本包装在一个函数中,并返回一个具有您想要的"public"函数的对象,这可能很繁琐,并且很难维护。
1 2 3 4 5 6 7 8 | var myLib = function() { //entire script return { functionA : functionA, functionB : functionB, //rest of functions } } |
或者像这样(中间调用的函数)
1 2 3 4 5 6 7 8 | (function(global) { //entire script myLib.functionA = functionA; myLib.functionB = functionB; //rest of fn global.myLib = myLib; })(window); |
你可以使用Gulp自动完成这个,我不确定是否有一个好的插件。