更多概況請看http://blog.zhangbing.club/%E…
下面例舉了一樣平常前段開闢中碰到的場景,處理計劃有許多,但從開闢階段就進行範例,能夠很大水平防止許多後續的潛伏和兼容題目。
獵取body元素
非規範做法
document.body
W3C範例要領
document.getElementsByTagName('body').item(0)
運用jQuery/Zepto
$('body');
獵取窗口題目
非規範做法
document.title
W3C範例要領
document.getElementsByTagName('title').item(0).innerHTML
運用jQuery/Zepto
$('title').text()
監聽iframe的加載完成事宜
- 寫法1:
iframe.onload = function() {...}
題目:存在兼容性題目,IE6、7無效
- 寫法2:
iframe.onload = iframe.onreadystatechange = function(){...}
題目:邏輯龐雜,事宜綁定邏輯雜沓,在某些瀏覽器上onload和onreadystatechange都邑觸發,需要另外加標記位推斷,邏輯龐雜。
- 簡約而完整兼容的寫法:
var bindIframeOnloadEvent = function(el, onload) {
if (el.attachEvent){
el.attachEvent("onload", onload);
} else {
el.onload = onload;
}
};
bindIframeOnloadEvent(iframe, function(){...});
怎樣操縱iframe內部的window
- 寫法1:
iframe.contentWindow
題目: 部份瀏覽器不兼容(IE67),獵取失利
- 寫法2:
document.frames[frameId]
題目: 非規範挪用,兼容性是題目,強迫必需為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繼承頭疼
- 終究處理計劃:
iframe.boder = 0;
iframe.style.boder = 'none';
怎樣在a標籤上綁定鼠標點擊事宜
- 寫法1:
<a href="javascript:func();">test</a>
題目:
- 不符合CSP範例
- 等價於全局eval。只能挪用公然的全局要領,污染全局變量
- 鼠標懸停時,狀態欄會顯現要運轉的代碼?!這對終究用戶不友好
- 運轉代碼的上下文是window對象,和事宜處置懲罰模子相違犯
- 寫法2:
<a href="#" onclick="func();">test</a>
題目:
- 不符合CSP範例
- onclick和href在部份瀏覽器(IE繼承躺槍)行文詭異,實行爭執非常
- 等價於全局eval。只能挪用公然的全局要領,污染全局變量(緣由同寫法1)
- 寫法3:
<a href="#" onclick="func();return false;">test</a>
題目:只處理了題目2,其他題目仍存在
- 規範寫法:
<a id='aTest'>test</a>
<script>
document.getElementById('aTest').onclick = function() {
func();
};
</script>
運用jQuery/Zepto亦可,存在唯一的小題目是鼠標指針不是手形,是默許。可採用CSS款式來處理cursor:pointer 。
script標籤的謄寫要領深挖
要點
- script標籤的type屬性不是必需的,默許缺省就是text/javascript
- script標籤的language屬性完整無用(asp時期微軟好像運用該屬性來標記服務端言語是vb照樣c#),不要弄巧成拙
- 動態建立的script標籤必需要指定type=’text/javascript’,不然JS不會實行
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '###';
document.getElementsByTagName('body').item(0).appendChild(script);
- 動態建立的script追加行動是異步的,並不會馬上獲得script運轉效果,假如要守候加載完成需要監聽完成事宜
- 運用非規範或許比較新的屬性需要分外注重,不要使代碼邏輯依靠於這些特徵。如defer/async屬性
- 運用script.onerror來監聽劇本實行失利的狀況(語法毛病,初始化運轉時毛病等都邑觸發)
- 監聽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函數不要運用
緣由:非規範,在部份瀏覽器報錯,以至連我的Android4.0上的瀏覽器都不認該函數
替換計劃:運用substring函數。
jQuery/Zepto挑選器的.text()和.html()要領
近況:大多數開闢同學會殽雜二者並亂花,不清楚什麼時候用哪一個
詳解:.text()要領用於獵取和設置文本內容,.html()要領用戶獵取和設置HTML內容,當要設置或獵取的內容僅僅為文本時,二者行動完整相同,但要操縱的文本內容是HTML時,行動有着本質區別。
總結:
- 依據實際需要挑選運用哪一個要領,如能判斷內容為純文本請運用text()要領。僅當確切需要襯着HTML時才用html()要領
- 從平安角度,text()要領比html()要領更平安,無注入風險。
- 嚴厲意義上,html()要領不符合CSP範例,直接將字符串剖析為DOM節點
- 營業需要確切要運用.html()要領襯着動態內容時,必需做平安搜檢,防止惡意代碼注入
- .text()和.html()獵取值能夠存在代碼縮進(空格和TAB),若有需要能夠運用$.trim()來剔除
數組與對象深挖
要點:
- 數組對象唯一concat/reverse/slice/splice為規範API,而且相對完整兼容
- 數組對象請勿運用indexOf、lastIndexOf、map、every、forEach等非規範API,不僅兼容性存在題目,而且效力不一定高,反而不如本身完成
- 遍曆數組請將.length緩存到變量
for(vari=0,l=arr.length;i<l;i++){...}
- 遍曆數組請勿運用此寫法
for(vari in arr){...}
- 遍歷key-value型對象必需運用hasOwnProperty()來過濾遍歷效果。
for(var key in obj) {
if(!obj.hasOwnProperty(key) continue;
//...
}
- 不論是數組或對象,在遍歷操縱時不要轉變被遍歷的變量組織,如增刪元素,增刪key值等(雖然你能夠這麼做),關於元素本身及子成員的修正是相對平安的。
關於Prototype的運用
要點:
- 不要亂花Prototype。不要隨意馬虎在Object/Array/Function等對象上追加prototype(雖然我們已有某些庫這麼做了)輕易發生歧義爭執,在運用for~in遍用時很輕易激發題目。
- 自定義的prototype成員會在for~in輪迴中湧現,請依據實際狀況運用hasOwnProperty()來過濾遍歷效果。
不嚴謹的寫法:
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}
嚴謹的寫法:
var o = new Test();
for(vari in o) {
if(!o.hasOwnProperty(i)) continue;
console.log({key: i, value: o});
}
//無輸出
- 對象的__proto成員,用處是獵取當前實例的原型對象。非規範完成,存在兼容性題目,請不要運用
- 原則上不要隨意馬虎重寫已存在的prototype要領。但能夠在單個實例中覆寫該要領
- prototype上定義靜態對象變量,會形成一切對象共用,而不是離別建立實例,請在組織要領中分派實例
毛病寫法:
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]
總結
JS是門天真的言語,天真到想怎樣寫都能夠。但內里坑照樣不少的。在有多種挑選時,多斟酌下哪一種要領更好,而不是自覺挑選一種。