摘要:更多詳情請看下面例舉了日常前段開發(fā)中遇到的場景,解決方案有很多,但從開發(fā)階段就進行規(guī)范,可以很大程度避免很多后續(xù)的潛在和兼容問題。
更多詳情請看http://blog.zhangbing.club/%E...
下面例舉了日常前段開發(fā)中遇到的場景,解決方案有很多,但從開發(fā)階段就進行規(guī)范,可以很大程度避免很多后續(xù)的潛在和兼容問題。
獲取body元素非標準做法
document.body
W3C規(guī)范方法
document.getElementsByTagName("body").item(0)
使用jQuery/Zepto
$("body");獲取窗口標題
非標準做法
document.title
W3C規(guī)范方法
document.getElementsByTagName("title").item(0).innerHTML
使用jQuery/Zepto
$("title").text()監(jiān)聽iframe的加載完成事件
寫法1:
iframe.onload = function() {...}
問題:存在兼容性問題,IE6、7無效
寫法2:
iframe.onload = iframe.onreadystatechange = function(){...}
問題:邏輯復雜,事件綁定邏輯混亂,在某些瀏覽器上onload和onreadystatechange都會觸發(fā),需要另外加標記位判斷,邏輯復雜。
簡潔而完全兼容的寫法:
var bindIframeOnloadEvent = function(el, onload) { if (el.attachEvent){ el.attachEvent("onload", onload); } else { el.onload = onload; } }; bindIframeOnloadEvent(iframe, function(){...});如何操作iframe內(nèi)部的window
寫法1:
iframe.contentWindow
問題: 部分瀏覽器不兼容(IE67),獲取失敗
寫法2:
document.frames[frameId]
問題: 非標準調(diào)用,兼容性是問題,強制必須為iframe添加ID。
簡潔而完全兼容的寫法:
var getIframeWindow = function(el) { return el.contentWindow || el.contentDocument.parentWindow; }; var win = getIframeWindow(iframe);設置iframe的邊框
寫法1:
iframe.boder = 0;
問題: 非W3C標準,后面很可能廢棄,部分瀏覽器不一定支持
寫法2:
iframe.style.boder = "none";
問題: 完全依賴CSS控制,但存在兼容性問題,IE繼續(xù)頭疼
最終解決方案:
iframe.boder = 0; iframe.style.boder = "none";如何在a標簽上綁定鼠標點擊事件
寫法1:
test
問題:
不符合CSP規(guī)范
等價于全局eval。只能調(diào)用公開的全局方法,污染全局變量
鼠標懸停時,狀態(tài)欄會顯示要運行的代碼?!這對最終用戶不友好
運行代碼的上下文是window對象,和事件處理模型相違背
寫法2:
test
問題:
不符合CSP規(guī)范
onclick和href在部分瀏覽器(IE繼續(xù)躺槍)行文詭異,執(zhí)行沖突異常
等價于全局eval。只能調(diào)用公開的全局方法,污染全局變量(原因同寫法1)
寫法3:
test
問題:只解決了問題2,其余問題仍存在
標準寫法:
test
使用jQuery/Zepto亦可,存在唯一的小問題是鼠標指針不是手形,是默認。可采用CSS樣式來解決cursor:pointer 。
script標簽的書寫方法深挖要點
script標簽的type屬性不是必須的,默認缺省就是text/javascript
script標簽的language屬性完全無用(asp時代微軟似乎使用該屬性來標記服務端語言是vb還是c#),不要畫蛇添足
動態(tài)創(chuàng)建的script標簽必須要指定type="text/javascript",否則JS不會執(zhí)行
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "###"; document.getElementsByTagName("body").item(0).appendChild(script);
動態(tài)創(chuàng)建的script追加動作是異步的,并不會立刻取得script運行結(jié)果,如果要等待加載完成需要監(jiān)聽完成事件
使用非標準或者比較新的屬性需要格外注意,不要使代碼邏輯依賴于這些特性。如defer/async屬性
使用script.onerror來監(jiān)聽腳本執(zhí)行失敗的情況(語法錯誤,初始化運行時錯誤等都會觸發(fā))
監(jiān)聽script的完成事件比較復雜。
varbindScriptOnloadEvent = function(script, onload) { var done = false; script.onload = script.onreadystatechange = function() { if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) { done = true; script.onload = script.onreadystatechange = null; onload(); } }; }; bindScriptOnloadEvent(script, function(){...});
需要考慮兼容性,所以代碼較多
substr函數(shù)不要使用原因:非標準,在部分瀏覽器報錯,甚至連我的Android4.0上的瀏覽器都不認該函數(shù)
替代方案:使用substring函數(shù)。
jQuery/Zepto選擇器的.text()和.html()方法現(xiàn)狀:大多數(shù)開發(fā)同學會混淆兩者并亂用,不清楚何時用哪個
詳解:.text()方法用于獲取和設置文本內(nèi)容,.html()方法用戶獲取和設置HTML內(nèi)容,當要設置或獲取的內(nèi)容僅僅為文本時,兩者行為完全相同,但要操作的文本內(nèi)容是HTML時,行為有著本質(zhì)區(qū)別。
總結(jié):
根據(jù)實際需要選擇使用哪個方法,如能斷定內(nèi)容為純文本請使用text()方法。僅當確實需要渲染HTML時才用html()方法
從安全角度,text()方法比html()方法更安全,無注入風險。
嚴格意義上,html()方法不符合CSP規(guī)范,直接將字符串解析為DOM節(jié)點
業(yè)務需要確實要使用.html()方法渲染動態(tài)內(nèi)容時,必須做安全檢查,避免惡意代碼注入
.text()和.html()獲取值可能存在代碼縮進(空格和TAB),如有需要可以使用$.trim()來剔除
數(shù)組與對象深挖要點:
數(shù)組對象僅有concat/reverse/slice/splice為標準API,而且絕對完全兼容
數(shù)組對象請勿使用indexOf、lastIndexOf、map、every、forEach等非標準API,不僅兼容性存在問題,而且效率不一定高,反而不如自己實現(xiàn)
遍歷數(shù)組請將.length緩存到變量
for(vari=0,l=arr.length;i遍歷數(shù)組請勿使用此寫法
for(vari in arr){...}遍歷key-value型對象必須使用hasOwnProperty()來過濾遍歷結(jié)果。
for(var key in obj) { if(!obj.hasOwnProperty(key) continue; //... }不論是數(shù)組或?qū)ο?,在遍歷操作時不要改變被遍歷的變量結(jié)構(gòu),如增刪元素,增刪key值等(雖然你可以這么做),對于元素自身及子成員的修改是絕對安全的。
關于Prototype的使用要點:
不要亂用Prototype。不要輕易在Object/Array/Function等對象上追加prototype(雖然我們已有某些庫這么做了)容易產(chǎn)生歧義沖突,在使用for~in遍歷時很容易引發(fā)問題。
自定義的prototype成員會在for~in循環(huán)中出現(xiàn),請根據(jù)實際情況使用hasOwnProperty()來過濾遍歷結(jié)果。
不嚴謹?shù)膶懛ǎ?/p>
function Test() {} Test.prototype.a = 1; Test.prototype.b = 2; var o = new Test(); for(vari in o) { console.log({key: i, value: o}); } //{key:a, value:1} //{key:b, value:2} 嚴謹?shù)膶懛ǎ?var o = new Test(); for(vari in o) { if(!o.hasOwnProperty(i)) continue; console.log({key: i, value: o}); } //無輸出對象的__proto成員,用途是獲取當前實例的原型對象。非標準實現(xiàn),存在兼容性問題,請不要使用
原則上不要輕易重寫已存在的prototype方法。但可以在單個實例中覆寫該方法
prototype上定義靜態(tài)對象變量,會造成所有對象共用,而不是分別創(chuàng)建實例,請在構(gòu)造方法中分配實例
錯誤寫法:
function Test() {} Test.prototype.arr = []; var a = new Test(); var b = new Test(); a.arr.push(1); b.arr.push(2); console.log(a.arr, b.arr); //[1,2], [1,2] 正確寫法 function Test() { this.arr = []; } var a = new Test(); var b = new Test(); a.arr.push(1); b.arr.push(2); console.log(a.arr, b.arr); //[1], [2]總結(jié)JS是門靈活的語言,靈活到想怎么寫都可以。但里面坑還是不少的。在有多種選擇時,多考慮下哪種方法更好,而不是盲目選擇一種。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95778.html
摘要:續(xù)前文后端好書閱讀與推薦,幾十天過去了,又看了兩本好書還有以前看過的書,這里依然把它們總結(jié)歸納一下,加入一些自己的看法有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。 續(xù)前文 后端好書閱讀與推薦 - Mageek`s Wonderland ,幾十天過去了,又看了兩本好書(還有以前看過的書),這里依然把它們總結(jié)歸納一下,加入一些自己的看法、有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。...
摘要:續(xù)前文后端好書閱讀與推薦,幾十天過去了,又看了兩本好書還有以前看過的書,這里依然把它們總結(jié)歸納一下,加入一些自己的看法有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。 續(xù)前文 后端好書閱讀與推薦 - Mageek`s Wonderland ,幾十天過去了,又看了兩本好書(還有以前看過的書),這里依然把它們總結(jié)歸納一下,加入一些自己的看法、有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。...
摘要:請注意,我們在聊聊單元測試遇到問題多思考多查閱多驗證,方能有所得,再勤快點樂于分享,才能寫出好文章。單元測試是指對軟件中的最小可測試單元進行檢查和驗證。 JAVA容器-自問自答學HashMap 這次我和大家一起學習HashMap,HashMap我們在工作中經(jīng)常會使用,而且面試中也很頻繁會問到,因為它里面蘊含著很多知識點,可以很好的考察個人基礎。但一個這么重要的東西,我為什么沒有在一開始...
閱讀 3012·2021-11-24 10:22
閱讀 3058·2021-11-23 10:10
閱讀 1367·2021-09-28 09:35
閱讀 1761·2019-08-29 13:16
閱讀 1400·2019-08-26 13:29
閱讀 2798·2019-08-26 10:27
閱讀 687·2019-08-26 10:09
閱讀 1450·2019-08-23 18:05