這實際上是相當簡單和寫這樣的腳本一個有趣的任務。
這是一個長期的例子,如何把一個普通函數弄成這個樣子:
我與假想腳本啓動。我已經包括它加載異步JavaScript文件中的scriptLoader:在DOM loadScript("/url.js")
它會插入一個新的腳本(第一個腳本標記之前)和瀏覽器會下載腳本:
window.loadScript = function(src){
const scriptTag = document.createElement('script');
scriptTag.async = true;
scriptTag.src = src;
const anyOtherScriptTag = document.getElementsByTagName('script')[0];
anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag);
}
當這樣調用。
到目前爲止這麼好。假設我想在加載之前傳遞這個腳本參數。在將被加載的腳本中,我訪問一個唯一的全局對象。我們稱之爲window.myScriptArgs
。所以理想情況下,一旦腳本已經加載,它將讀取window.myScriptArgs並相應地執行。現在
我可以做window.myScriptArgs = []
和收工,但是因爲我的假設的例子只會加載單腳本文件,我的邏輯添加到loadScript功能以及。
window.loadScript = function(src){
window.myScriptArgs = window.myScriptArgs || [];
const scriptTag = document.createElement('script');
scriptTag.async = true;
scriptTag.src = src;
const anyOtherScriptTag = document.getElementsByTagName('script')[0];
anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag);
}
loadScript("/my-script.js");
好了,所以我檢查是否myScriptArgs已經存在,如果沒有我將其設置爲空數組。 現在我也知道my-script.js
公開全局myScript()方法。所以我爲它寫了一個存根。這存根將把每說法得到它進入myScriptArgs數組:
window.myScript =() => {
window.myScriptArgs = window.myScriptArgs || [];
window.myScriptArgs.push(arguments);
}
現在我可以打電話loadScript並立即撥打myScript的()用給定的參數。無需擔心加載問題或不需要。一旦「my-script.js」被加載,它讀取window.myScriptArgs
,並作爲例外。代碼如下所示:
window.myScript =() => {
window.myScriptArgs = window.myScriptArgs || [];
window.myScriptArgs.push(arguments);
}
window.loadScript = function(src){
window.myScriptArgs = window.myScriptArgs || [];
const scriptTag = document.createElement('script');
scriptTag.async = true;
scriptTag.src = src;
const anyOtherScriptTag = document.getElementsByTagName('script')[0];
anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag);
}
loadScript("/my-script.js");
myScript('command', 'args', 'args1');
myScript('command2', 'args3', 'args4');
好的,按預期工作。讓我們優化它。首先,我的loadScript
和myScript
存根相結合,被稱爲initMyScript()一個單一的功能:
window.initMyScript = function(src){
window.myScriptArgs = window.myScriptArgs || [];
window.myScript = window.myScript || function(){
window.myScriptArgs.push(arguments);
}
const scriptTag = document.createElement('script');
scriptTag.async = true;
scriptTag.src = src;
const anyOtherScriptTag = document.getElementsByTagName('script')[0];
anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag);
}
initMyScript("/my-script.js");
myScript('command', 'args', 'args1');
myScript('command2', 'args3', 'args4');
這沒有什麼太花哨大氣壓。現在,我將通過將window
作爲參數傳遞給initMyScript
來擺脫多個window.
調用。我也會用document
來做到這一點。
腳本是這樣的:
window.initMyScript = function(p, a, src){
p.myScriptArgs = p.myScriptArgs || [];
p.myScript = p.myScript || function(){
p.myScriptArgs.push(arguments);
}
const scriptTag = a.createElement('script');
scriptTag.async = true;
scriptTag.src = src;
const anyOtherScriptTag = a.getElementsByTagName('script')[0];
anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag);
}
initMyScript(window, document, "/my-script.js");
現在讓我們來看看,我重複自己節省一些更多的比特。我使用的字符串script
兩次,同爲myScript
:
window.initMyScript = function(p, a, s, c, src){
p.myScriptArgs = p.myScriptArgs || [];
p[c] = p[c] || function(){
p.myScriptArgs.push(arguments);
}
const scriptTag = a.createElement(s);
scriptTag.async = true;
scriptTag.src = src;
const anyOtherScriptTag = a.getElementsByTagName(s)[0];
anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag);
}
initMyScript(window, document, 'script', 'myScript', "/my-script.js");
在我的旅途下一步是使變量短。而且我也把這個功能變成一個自動執行功能,節省了window.initMyScript
定義:
(function(p, a, s, c, src){
p.myScriptArgs = p.myScriptArgs || [];
p[c] = p[c] || function(){
p.myScriptArgs.push(arguments);
}
const q = a.createElement(s);
q.async = true;
q.src = src;
const d = a.getElementsByTagName(s)[0];
d.parentNode.insertBefore(q, d);
})(window, document, 'script', 'myScript', "/my-script.js");
和我最後的神祕:我編輯的功能參數來迷惑人,也更再縮小代碼。你可以使用逗號實際鏈接JavaScript中的函數;)。
(function(p, a, s, c, A, l, i){
p["myScriptArgs"]=p["myScriptArgs"]||[],p[c] = p[c]||function(){
p["myScriptArgs"].push(arguments)},
l = a.createElement(s);l.async = true;l[A] = A;
i = a.getElementsByTagName(s)[0];
i.parentNode.insertBefore(l, i);
})(window, document, 'script', 'myScript', "/my-script.js");
myScript("arg1", "arg2");
myScript("arg2", "arg3");
請注意,我想補充兩個額外的參數的功能,那是因爲我需要保存由createElement
返回的元素,並且不希望使用var
聲明)。
你可以更進一步,但你明白了。對於小功能,您可以自己動手,沒有問題。
此外,您可以像使用UglifyJS一個minifier,然後自己重新命名後的變量,如果你真的成整體等值線圖的事情......
注:我沒有測試此代碼的任何。這裏是龍。 想象中的代碼是我糟糕的嘗試去混淆Google例子。谷歌分析代碼片段幾乎與我的自定義代碼片段相同。遺傳算法優化了一些(例如,變成1),但你明白了。
瞭解更多關於我的例子中使用過的東西: Immediately Invoked Function Expression Property accessors (especially Bracket notation)
和JavaScript具體的東西像傳遞三個參數傳遞給這需要5功能。
我不知道,但這是一個很小的腳本,它可以很容易地使用所需的函數參數名稱手工完成。 –
...有趣的是,'ga'腳本使用了括號表示法:'i ['GoogleAnalyticsObject']',其中minifiers(包括Closure Compiler)通常會轉換爲點語法,所以這讓我覺得它可能是手工完成的,括號用於防止它通過CC運行,所以它不會將它變成'window.b =「ga」'。 –
@squint謝謝!是的,它似乎是手工完成的,只是想知道我是不是缺少什麼東西 – lmenus