一般浏覽器先加載首頁,再請求關聯的js腳本檔案。不管你把js代碼嵌入在html中,還是獨立儲存為一個檔案,都必須等待首頁加載完成,js代碼加載完成後才能執行。網上有人說把js代碼放在head裡面,其實這樣并不影響腳本執行時機。因為js或html還沒有加載,何談執行js代碼。先看一下頁面加載資源的順序
浏覽器加載頁面資源順序
再簡單分析一下onload事件的執行時機。
Document.onload
它是在結構和樣式加載完才執行js。【就是在html和css都完事以後才執行】
Window.onload
它不僅僅要在結構和樣式加載完,還要執行完所有的樣式、圖檔這些資源檔案,全部加載完才會觸發window.onload事件。
jquery中的ready
指定在DOM完全加載時要執行的函數。
也許你又會想到,先執行JavaScript,再打開頁面可以嗎?答案是否定的,因為執行完JavaScript後,執行結果儲存在變量中,當打開一個新的頁面時,js變量會被清空。
有什麼方法在頁面加載前就執行js代碼呢,單從網頁來考慮似乎無解,那就需要從浏覽器端入手。當輸入網址或點選連結導緻需要加載另一個頁面前就執行js代碼(注意隻是準備加載頁面,還沒有下載下傳一個字元)。這樣做可以在頁面加載前先給某些變量指派,且這個變量值在頁面加載完成後不會消失。
打開木頭浏覽器的項目管理視窗,建立一個腳本代碼步驟,并輸入需要執行的JavaScript代碼,選擇代碼執行時機為“頁面加載前執行”,儲存這個項目後,隻要執行一次這個項目(點選測試也可以),在浏覽器中打開任何網址時,都會先執行這段JavaScript代碼。如下圖所示,為友善體驗具體效果,設定一個彈窗代碼在頁面加載前執行。
加載頁面前執行腳本
然後在浏覽器中輸入打開一個網址,此時頁面還沒有加載,就彈出了視窗。由于是模态彈窗,隻有點選确定後才會繼續加載頁面内容。頁面加載完成後,js變量值亦不會丢失。
執行時機測試
如果需要停止在頁面加載前執行腳本代碼,隻需要再添加一個腳本代碼步驟,代碼為空,設定執行時機為“停止加載前執行”。當此步驟執行一次後,在浏覽器打開網頁就不會再執行腳本代碼彈出視窗了。
停止加載前執行腳本
網頁加載前注入執行JavaScript腳本,具體有什麼作用呢?可以用于改變系統環境參數,比如修改螢幕分辨率;執行如下代碼後,網頁擷取分辨率時将得到預設值而非實際分辨率。
- screen.width = 1024;
- screen.height = 768;
- screen.availWidth = 1024;
- screen.availHeight =768;
- screen.availablewidth =1024;
- screen.availableheight =768;
還可以修改系統函數,替換函數功能。比如把下面這段代碼放在頁面加載前執行,改變系統的alert函數功能,那麼此頁面再執行alert就不會彈出視窗了。
- window.alert=function(txt){
- return txt;
- }
某些網站通過JavaScript功能函數采集“浏覽器指紋”,同樣可以通過修改功能函數,避免被網站跟蹤。比如在頁面加載前執行以下代碼,自動給canvas畫布指紋添加變化的噪聲,導緻頁面每次擷取的“浏覽器指紋”都不一樣。
- var inject = function () {
- const toBlob = HTMLCanvasElement.prototype.toBlob;
- const toDataURL = HTMLCanvasElement.prototype.toDataURL;
- const getImageData = CanvasRenderingContext2D.prototype.getImageData;
- //
- var noisify = function (canvas, context) {
- if (context) {
- const shift = {
- 'r': Math.floor(Math.random() * 10) - 5,
- 'g': Math.floor(Math.random() * 10) - 5,
- 'b': Math.floor(Math.random() * 10) - 5,
- 'a': Math.floor(Math.random() * 10) - 5
- };
- //
- const width = canvas.width;
- const height = canvas.height;
- if (width && height) {
- const imageData = getImageData.apply(context, [0, 0, width, height]);
- for (let i = 0; i < height; i++) {
- for (let j = 0; j < width; j++) {
- const n = ((i * (width * 4)) + (j * 4));
- imageData.data[n + 0] = imageData.data[n + 0] + shift.r;
- imageData.data[n + 1] = imageData.data[n + 1] + shift.g;
- imageData.data[n + 2] = imageData.data[n + 2] + shift.b;
- imageData.data[n + 3] = imageData.data[n + 3] + shift.a;
- }
- }
- //
- window.top.postMessage("canvas-fingerprint-defender-alert", '*');
- context.putImageData(imageData, 0, 0);
- }
- }
- };
- //
- Object.defineProperty(HTMLCanvasElement.prototype, "toBlob", {
- "value": function () {
- noisify(this, this.getContext("2d"));
- return toBlob.apply(this, arguments);
- }
- });
- //
- Object.defineProperty(HTMLCanvasElement.prototype, "toDataURL", {
- "value": function () {
- noisify(this, this.getContext("2d"));
- return toDataURL.apply(this, arguments);
- }
- });
- //
- Object.defineProperty(CanvasRenderingContext2D.prototype, "getImageData", {
- "value": function () {
- noisify(this.canvas, this);
- return getImageData.apply(this, arguments);
- }
- });
- //
- document.documentElement.dataset.cbscriptallow = true;
- };
- inject();