開發中遇到的一些技巧和坑

let test = 'test string';
let str = 'this is a '+ test; 
let str2 = `this is a ${test}`;//推薦用法,注意這裏的`號不是單引號

由於模板字符串爲es6的語法,不建議在前端js使用,由於目前瀏覽器對es6支持不完整前端

善於使用邏輯運算符來簡化代碼

** !!**mysql

let obj = null;
let boolean = !!(''); //使用兩個邏輯非能夠獲取準確的布爾值結果

** ||**es6

if(obj === null || obj === '' || obj === undefined || obj === 0){
   obj = '';
}

簡化爲:sql

obj = obj || '';//此處注意obj的值在什麼狀況下是false

** &&**數據庫

if(obj !== null){
   obj = 'has value';
}

簡化爲:數組

obj !== null && (obj = 'has value');

** ~**promise

if(str.indexOf('a') > -1){
    ...
}

簡化爲:瀏覽器

if(~str.indexOf('a')){
    ...
}

多條件分支語句的簡化

多條件分支語句若是執行邏輯相似或相同時,可使用簡化寫法。(邏輯不一樣也能夠,但須要提取爲獨立的處理方法)babel

if寫法markdown

if(flag == 1){
   retrun test1();
}else if(flag == 2){
   return test2();
}else if(flag == 3){
   return test3();
}else if(flag == 4){
   return test4();
}else if(flag == 5){
   retrun test5();
......
}else{
   retrun test();
}

switch寫法

switch(flag){
  case 1:
    retrun test1();
    break;
   case 2:
    retrun test2();
    break;
   case 3:
    retrun test3();
    break;
   case 4:
    retrun test4();
    break;
   case 5:
    retrun test5();
    break;
  ......
   default:
     retrun test();
     break;
}

上述語句均可以簡寫爲:

let caseList = {1: test1, 2: test2, 3: test3, 4: test4, 5: test5 ......};
if(flag && flag in caseList){
    return caseList[flag] (); //此處爲了markdown正常顯示,多打了一個空格
} else {
    retrun test();
}

使用Promise.all來處理批量異步(無依賴)

某些狀況下咱們須要循環進行異步處理,不少人這樣寫:

for(let n in obj){
    await this.model.where({id: obj[n]['id']}).update({status: 1});
}

在併發量大或者數據庫數據量大的狀況下,理論上的處理時間和爲 (單個異步處理時間 * obj.length),會出現性能問題,推薦的寫法是:

let ps = [];
for(let n in obj){
    ps.push(this.model.where({id: obj[n]['id']}).update({status: 1}));//將異步事件放入數組
}
await Promise.all(ps);//並行處理

理論上處理時間和爲 max(每一個異步處理時間)

無依賴是指,下次循環不須要依賴當前循環的異步事件結果。若是有依賴此方法不適用

慎用連續賦值

一個例子:

let a = {"n" : 1};
let b = a;
a.x = a = {"n": 2};

console.log(a.x);//undefined
console.log(b.x);//{"n": 2}

乍一看,很容易弄錯結果,覺得a.x的值是{「n」: 2};其實否則,由於.運算符比賦值運算符優先級高,因此a.x賦值後,a再次賦值,指針變化了,a.x屬性丟失

推薦寫法:

let a = {"n" : 1};
let b = a;
a.x = {"n": 2};
a = {"n": 2}; //此處明顯看出a的指針變化,x屬性丟失

console.log(a.x);//undefined
console.log(b.x);//{"n": 2}

箭頭函數內部沒法使用 async/await

錯誤代碼:

return promise.then(data => {
    let info = await this.model.find(); //錯誤
    ...
});

正確代碼:

return promise.then(data => {
    return this.model.find();
}).then(info => {
    ...
});

空模型實例化後僅能夠工做在mysql數據源

M('').query('select * from test'); //僅適用於mysql

mongoDb不能使用空模型,必須有對應的實體類:

M('Test').query('db.test.findOne()');

super不能和async/await並存

錯誤代碼:

if(true){
    await this.model.where({id:1}).update({name: 'test'});
}
return super.indexAction();//此處使用到了super調用父類方法,但在上面的語句中使用了await,被babel編譯以後,致使做用域混亂,控制器實例化失敗

正確代碼:

let promise = getPromise();
if(true){
    promise = this.model.where({id: 1}).update({name: 'test'});
}
return promise.then(() => {
    return super.indexAction();//注意此處的super在箭頭函數內,綁定的做用域爲控制器
});

錯誤代碼2:

await super.test(); //await被babel編譯後成爲Generator函數,在函數體內調用super致使做用域混亂
return this.render();

正確代碼2:

return super.test().then(() => this.render());

extend函數的淺繼承和深繼承

extend函數是ThinkNode框架提供的一個很是有用的函數,來自於jQuery。能夠實現對象和數組的繼承和克隆。可是在使用中必定要注意淺繼承和深繼承的區別。

淺繼承舉例:

let data = {"aa": {"qq": 555555}};
let temp = extend(false, {}, data);//第一個參數爲false,淺繼承
temp.aa.qq = 222222;
console.log(data); //{ aa: { qq: 222222 } } //原始對象data被污染
console.log(temp); //{ aa: { qq: 222222 } }

深繼承舉例:

let data = {"aa": {"qq": 555555}};
let temp2 = extend({}, data); //深繼承
temp2.aa.qq = 222222;
console.log(data); //{ aa: { qq: 555555 } } //原始對象未被污染
console.log(temp2); //{ aa: { qq: 222222 } }

區別是淺繼承僅僅複製了父對象的屬性值(基礎數據類型),若是父對象的屬性值爲一個對象(或數組),僅僅是賦值(指針指向)而非複製;

相關文章
相關標籤/搜索