js代碼常見技巧總結

寫在前面

(可貴從繁重的業務代碼中抽身,更新一下文章)前端框架和技術日益發展,可是無論怎麼變,js永遠都是最重要的基礎,本文記錄和總結一些平常開發中常見的js代碼技巧和誤區,不按期更新。前端

正文

1. 避免鏈式聲明

後果:可能引入全局變量chrome

//錯誤的寫法
    var a = b = 0;

這段代碼中,b實際上被聲明爲全局變量。由於操做符優先級是是從右往左,因此該語句至關於:segmentfault

var a = (b = 0)

此時b未聲明就被直接賦值,因此b成了全局變量數組

2. 單一var原則

這條規則的意思是,把函數內部的全部變量,放到頂部聲明。好比:瀏覽器

//示例
    function A(){
      var a = 1,
          b = 2,
          c = a + b ;
    }

優勢:緩存

  • 便於查找函數內部使用的局部變量
  • 防止變量未定義時就被使用
  • 防止變量聲明提高後引起的誤解

關於第三點,這裏舉個例子說明:前端框架

var x = 1;
  function A(){
    console.log(x);//第一處輸出 ,注意結果
    var x = 2;
    console.log(x);//第二處輸出 2,沒問題
  }

從代碼上看,第二處輸出確定沒問題,可能會有人認爲第一處輸出的是1,由於此時在函數內部還沒聲明變量x,根據做用域鏈,向外層查找的話,x值爲1。可是實際輸出的值應該是undefined,由於js容許在函數任何地方聲明變量,而且不管在哪裏聲明都等同於在頂部聲明,這就是聲明提高。因此上面的代碼至關於:框架

var x = 1;
  function A(){
    var x;//提高到頂部
    console.log(x);//此時已聲明 未賦值
    x = 2;//賦值
    console.log(x);
  }

3. 使用for循環時,緩存長度值

一般用使用for循環遍歷數組時,會採用如下寫法:dom

for(var i = 0;i<arr.length;i++){
 // 具體操做
}

這段代碼存在的問題在於,在循環的每一個迭代步驟,都必須訪問一次arr的長度。若是arr是靜態數值還好,可是咱們在使用js時可能會碰到arr是dom元素對象,因爲dom對象載頁面下是活動的查詢,這個長度查詢就至關耗時函數

//用len緩存長度值
for(var i = 0,len = arr.length;i<len;i++){
 // 具體操做
}

按照上面的代碼,咱們在第一次獲取長度值時就緩存這個長度值,就能夠避免上述問題。

4. 使用for-in時,增長hasOwnProperty()判斷

for-in一般用來枚舉對象的屬性和方法,可是這個方法會枚舉範圍包括對象和對象的原型對象(對原型對象不瞭解的能夠看看我以前寫的文章傳送門)此時,利用hasOwnProperty()方法能夠幫咱們過濾出只在對象自己上的屬性和方法,或者只在原型鏈的屬性和方法

for(var key in obj){
   if(obj.hasOwnProperty(key)){
     // 對象自己的屬性或者方法
  }
  else{
     // 原型鏈的屬性和方法
  }
}

/* 下面是一個具體的例子 */
 function A(name){
    this.type = 'A類';
    this.name = name || '未命名'
}

var a = new A('a');

function B(name){
  this.subtype = 'B類';
}

// 創建原型鏈
B.prototype = a;
B.prototype.sayHello = function(){}

var b = new B();

// 遍歷屬性
for(var key in b){
  //對象自身屬性
  if(b.hasOwnProperty(key)){
    console.log('對象自身的屬性或方法:'+key) 
  }

  //上述表達式的另外一種寫法
  if(Object.prototype.hasOwnProperty.call(b,key)){
    console.log('對象自身的屬性或方法:'+key)
  }
  else {
    console.log('原型鏈的屬性或方法:'+key)
  }
}

5. 使用===代替==

這個算是比較常見的了,由於js在作比較判斷時,會執行強制類型轉換,好比false == 0返回true這樣的狀況,使用===能夠執行嚴格的等價比較,更易於閱讀代碼(後來閱讀的人就不須要判斷這個是遺漏仍是故意使用強制類型轉換簡寫)

6. 使用parseInt()時,帶上第二個參數。

parseInt()用於從字符串中獲取數值,第二個參數表明進制,默認是10。咱們在使用的時候可能習慣性忽略這個參數,可是在一些狀況下會有問題:當字符串的開頭爲0時,在es3裏會被當作是八進制,es5裏面仍然當作10進制,爲了代碼的一致性以及避免沒必要要的失誤,應該每次使用時都帶上參數:

var x = parseInt('089',10);//使用時都帶上進制參數

7. 大括號的使用

大括號的使用主要是2個方面:

  • 第1,不要省略大括號,即便能夠忽略,好比:
for(var i =1;i<10 ;i++)
    console.log(i) //此處原則上能夠忽略大括號

上述語句並無問題,可是若是後期函數體內增長了其餘語句的時候,很容易忘記補上大括號,所以建議都帶上大括號;

  • 第2,大括號的必須跟在前一個語句的同一行

這個地方爲何加粗了呢?由於這個問題很是容易被忽略,一般咱們都以爲大括號是跟在語句的同一行仍是下一行只是習慣問題,可是實際上不是的!看下面這個例子:

function func(){
  return 
  {
    name:'xxx'
  }
}
var res = func()
console.log(res)//輸出undefined

是否是以爲很奇怪,看代碼第一感受應該是輸出一個包含name屬性的對象。請注意,因爲js的分號插入機制:若是語句沒有使用分號結束,會自動補充分號,所以上面的代碼實際至關於以下寫法:

function func(){
  return undefined;//自動插入分號
  {
    name:'xxx'
  }
}

正確的寫法應該是:

function func(){
  return {
    name:'xxx'
  }
}
var res = func()
console.log(res)//輸出{name:'xxx'}

----------------------06.15更新------------------------

8 . 判斷語句的優化

在業務中常常會遇到相似對請求結果判斷後讀取的狀況。好比:

requset().then(function(res){
    if(res){
        //對返回數據進行操做的代碼
    } else{
        
    }
})

這種寫法沒有問題,可是有時候邏輯比較長,嵌套的大括號比較多。此時能夠採用另外一種寫法

requset().then(function(res){
    // 先判斷!res
    if(!res){
        ///
    }
    //對返回數據進行操做的代碼
})

這種寫法能夠減小一次嵌套,在邏輯判斷較多時,嵌套層數減小能夠增長代碼可讀性。

----------------------06.20更新------------------------

9 . 對url進行encode

此條主要是在這兩天修復一個遺留bug時候發現,一個上傳組件在ie下失效,其中一個緣由是上傳的請求url參數中包含中文參數,可是未手動encodeURI,原先的開發者可能只考慮了chrome下的狀況。因爲chrome會自動對url進行encode,因此很容易忽略其餘瀏覽器,爲了不此類的兼容問題,建議老是手動作好編碼處理。

----------------------08.16更新------------------------

10.空對象判斷(要考慮不可枚舉屬性)

先上代碼:

function X() {

  }
  //原型上的屬性
  X.prototype.age = '22'
  var x = new X()
  Object.defineProperty(x, 'name', {
    enumerable: false,
    value: '張三'
  })
  console.log(x)

  //方法1 使用for...in遍歷
  function isEmptyObject1(obj) {
    for (var attr in obj) {
      return false
    }
    return true
  }

  //方法2 使用JSON.stringify
  function isEmptyObject2(obj) {
    return (JSON.stringify(obj) === '{}')
  }

  //方法3 使用Object.keys
  function isEmptyObject3(obj) {
    return Object.keys(obj).length === 0
  }

  //方法4 使用getOwnPropertyNames

  function isEmptyObject4(obj) {
    return Object.getOwnPropertyNames(obj).length === 0
  }
  console.log(isEmptyObject1(x)) //true
  console.log(isEmptyObject2(x)) //true
  console.log(isEmptyObject3(x)) //true
  console.log(isEmptyObject4(x)) //false

----------------------2019.01.17更新------------------------

11.封裝請求函數時,考慮使用對象代替數組傳參

// 1.使用數組方式傳參,須要嚴格按照參數順序,而且對於多個可選參數的狀況很差處理
const getMethod = (id,uid,option1,option2)=>{
    const config = {
        // 參數處理
    } 
    request.get(config)
}
// 若是此時可選參數1不傳,卻要傳入可選參數2,則必須傳入空值佔位
getMethod('e3ruewruwieru','231423asd',null,'asdasd')

// 2. 使用對象傳參時,能夠不按照順序傳入參數
const getMethod  = (query) =>{
    const { id, uid, option1,option2} = query //直接解構出須要的參數
    const config = {
        option1:option1 ||'' //即便多個可選參數,處理起來也很方便
    } 
    request.get(config)
}
// 使用比較靈活 而且不用考慮參數順序
const query = {
    id:'123',
    uid:'asd',
    option2:'goodjob'
}
getMethod(query)

小結

本文會長期更新和補充(若是我沒被淹沒在業務中的話),歡迎讀者提出建議和意見。

而後依然是每次都同樣的結尾,若是內容有錯誤的地方歡迎指出;若是對你有幫助,歡迎點贊和收藏,轉載請徵得贊成後著明出處,若是有問題也歡迎私信交流,主頁添加了郵箱地址~溜了

相關文章
相關標籤/搜索