開發chrome插件時遇到須要獲取原始網頁中的一個js變量的值問題。因爲content.js和原始網頁的做用域環境不一樣,沒法直接獲取變量的值,提示undefined。谷歌找到大神提供的辦法。綜合起來記錄以下:javascript
考慮到Google Reader的網頁太複雜,這裏就以Google首頁來舉例了。打開網頁後,右鍵打開審查元素,而後在控制檯輸入fp,就會看到一個字符串,這就是原始網頁的一個全局變量。
如今我要獲取它,就能夠建立一個script元素,append到head。而這個script元素的執行環境是原始網頁的,能夠自由使用fp這個變量。
不過fp取出來後也無法直接傳遞迴content script。好在文檔裏說DOM是共用的,因此能夠在這個script裏,把值設置爲某個元素的屬性或innerText,再在content script裏獲取就好了:java
setTimeout(function() { var script = document.createElement('script'); script.type = 'text/javascript'; script.innerHTML = "document.body.setAttribute('data-fp', fp);"; document.head.appendChild(script); document.head.removeChild(script); console.log(document.body.getAttribute('data-fp')); }, 1000);
這裏延遲的緣由是原始網頁加載完時,還須要等一會纔會建立fp變量。
另外一種辦法就是使用location.href,它是用來跳轉網頁的,可是也能夠用來執行JavaScript,而且執行環境也是原始網頁:chrome
setTimeout(function() { location.href = "javascript:document.body.setAttribute('data-fp', fp);"; setTimeout(function() { console.log(document.body.getAttribute('data-fp')); }, 0); }, 1000);
這裏嵌套使用了setTimeout,緣由是跳轉是一個事件,並不會打斷當前腳本的執行(而添加script元素會馬上執行),所以須要讓後面的語句等待事件處理完畢。
不過前面所說的方法都必須先保存,再取出,能這樣作的只有字符串等簡單類型,對函數則無能爲力了。
實際上還有更方便的方法,那就是在DOM上綁定一個事件,而事件的處理函數則返回window變量,再在程序中觸發這個事件,就能得到執行環境的window變量了。幸運的是,這個執行環境仍然是原始網頁的:app
setTimeout(function() { var div = document.createElement('div'); div.setAttribute('onclick', 'return window;'); var unsafeWindow = div.onclick(); console.log(unsafeWindow.fp); }, 1000);