博客逐步遷移至 極客兔兔的小站javascript
Javascript的弱類型以及函數做用域等規則使用編寫Javascript代碼極爲容易,可是編寫可維護、高質量的代碼卻變得十分困難,這個系列的文章將總結在項目開發過程當中,可以改善代碼可讀性、可維護性及優化運行性能的一系列技巧。
若有問題,請不吝指出,很是感謝;若是喜歡,右下角點個推薦吧~java
var key = 'value'; // 全部函數外執行 window.key = 'value'; // window爲全局對象 key = 'value'; // 省去 var,隱式的全局變量
/** * 只有Person一個全局變量, * 其他變量定義在Person下,儘量地避免與其餘變量名衝突 */ var Person = { name:"A", age:20 }; Person.parents = { father:"A", mother:"C" } Person.getAge = function() { /* ... */ }
/** * 考慮下面的函數,先運行f1(),再var b = 4, * 可是事實上,f1()中的b就是以後定義的b * 這是變量提高特性形成的,就是說全部變量定義都將提到函數最前面 * 局部變量的優先級高於外部變量,所以f()外部的b至始至終沒有變過 */ var b = 15; var f = function() { var a = 100; var f1 = function(){ var c = 3; b = a + c; // => b=103 變量提高,這裏的b是函數f()內部的b }; f1(); var b = 4; console.log(a , b , c); // => a=100,b=4,c=undefined } f(); console.log(b); // => b=15,b並無發生改變
0.1 + 0.2 === 0.3 // => false
typeof null === 'null' // => false typeof null === 'object' // => true typeof NaN === 'NaN' // => false typeof NaN === 'number' // => true // javascript6個基本類型以下,typeof老是返回這6個值 // number、string、boolean、object、function、undefined // chrome 50中,typeof 3/0 結果爲 NaN,有博友知道爲何求告知
function type(ob){ return (ob === null ) ? "null" : (typeof ob); }
toString()
方法。// 更多內置類型,例如 Math 等能夠根據須要添加 function type(ob){ var _toString = Object.prototype.toString; var _type = { "undefined" : "undefined", "number" : "number", "boolean" : "boolean", "string" : "string", "[object Function]" : "function", "[object RegExp]" : "regexp", "[object Array]" : "array", "[object Date]" : "date", "[object Error]" : "error" } return _type[typeof ob] || _type[_toString.call(ob)] || (ob ? "object" : "null"); }
typeof NaN === 'number' // => true 類型爲number,表示非數字 '0.1223' // => 0.1223 '1e6' // => 1000000 '1a3' // => NaN 1.2 + NaN // => NaN
// 不能轉換爲數字的值,均返回true, // 所以並不能用這個函數檢測一個值是否真的爲 NaN isNaN(NaN) // => true isNaN('abc') // => true isNaN(0) // => false isNaN('1e6') // => false isNaN(3/0) // => fasle // NaN是一個惟一本身與本身不相等的值 NaN === NaN // false NaN !== NaN // true
// 方法一 function _isNaN(value){ return value !== value; } // 方法二 function _isNaN(value) { return typeof value === 'number' && isNaN(value); }
isNaN(3/0) // => fasle,雖然3/0 不能表明一個數,可是isNaN不能識別 isFinite(3/0) // => false,isFinite能檢測 NaN和正負無窮大 isFinite("234") // => true,isFinite 能夠將參數轉換爲數字 isFinite(true) // => true,可轉化爲數字的字符串和布爾值返回true
// 加一個基本類型判斷就OK function isNumber (value) { return typeof value === "number" && isFinite(value); }
undefined有以下幾種狀況python
(1) 定義了變量但沒有賦值 var cc; cc === undefined // => true (2) 獲取一個對象不存在的屬性 (3) 沒有返回值的函數,new + 構造函數除外(4) 定義函數時聲明多個形參,調用時傳入參數個數少於聲明,多餘的參數爲undefined面試
0、NaN、''(空字符串)、false、null、undefined的布爾值爲false(注意,[](空數組),{}(空對象)布爾值爲 true )chrome
var a = 4 ; if({})a++; // => a=5 空對象可經過 Object.keys().length判斷 if([])a++; // => a=6 空數組經過 length 判斷
'' == 0 // => true,String與Number,將String轉爲 Number 0 == '0' // => true,同上 '' == '0'// => false,2個都是字符串,所以直接比較 fasle == '0' // => true,Boolean與其餘,將Boolean轉爲Number true == '3' // => false,同上 false == undefined // => false,同上,0與undefined不等 false == 'false' // => false,同上 null == undefined // => true,null與undefined比較返回true
typeof value === 'object' && value.constructor === Array
/* 將arguments對象轉換爲數組 */ var args = Array.prototype.slice.call(arguments); /* 具備length屬性,鍵爲數字且從0開始的對象 */ a = {0:"c",1:"d",length:2 } Array.prototype.slice.call(a); // => ["c","d"] /* 沒有length屬性 */ a = {0:"c",1:"d"} Array.prototype.slice.call(a); // => [ ] 空數組 /* 猜想slice方法實現方式 */: function slice(ob){ var arr = new Array(); for(var i = 0; i < ob.length; i++ ){ arr[i] == ob[i]; } return arr; }
var ob = { a: 1, b: 2}; var d = 0; with(ob){ a = 3; // ob.a = 3 c = 4; // ob.c = undefined,window.c = 4,無意聲明瞭全局變量 d = 5; // ob.d = undefined, d爲with外申明的變量 }
不推薦使用with的3個理由數組
(1) 使用with時,先檢查對象是否有該屬性,存在則使用,不存在則繼續查找做用域,會下降執行性能
(2) with語句中的變量語意不明確,可讀性差
(3) 例如上例中的c不當心隱式聲明爲全局變量,本意是給ob.c賦值,易出現問題且難以調試安全
對於eval(),能夠直接執行一段js代碼,不推薦理由以下函數
(1) eval須要將字符串解釋爲代碼後執行,下降執行性能
(2) eval下降程序的可讀性,例如 eval("var a = ob." + key)等價於var a=ob[key],後者明顯更優
(3) eval存在安全問題,任意傳入字符串均可能被解析執行,惡意代碼也不例外性能
// 在須要貫穿的case語句後添加 /* empty */ // 避免檢查代碼時被認爲忘記寫了執行語句 // 顯示申明,語意也更明確,提升可讀性 switch(a){ case 1: /* empty */ case 2: func1(); break; case 3: func2(); break; }
if(a) if(b) func1(); else func2(); // => 等價於 if(a) if(b) func1(); else func2(); // 這並非想要的結果,js不是python,仍是加上大括號比較好
// 很清晰地看出 if(a) 和 else 並列 // if(b) 是 if(a) 的子語句 if(a){ if(b){ func1(); } }else{ func2(); }
分享創造價值,喜歡這個系列文章,不妨關注一下~優化