Skip to content

经验分享-提高生产效率的一些编码技巧(1) #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sunmaobin opened this issue Dec 1, 2017 · 0 comments
Open

经验分享-提高生产效率的一些编码技巧(1) #42

sunmaobin opened this issue Dec 1, 2017 · 0 comments

Comments

@sunmaobin
Copy link
Owner

sunmaobin commented Dec 1, 2017

经验分享-提高生产效率的一些编码技巧(1)

本文包含了一些个人开发经验总结和设计模式的总结,希望能给大家有所帮助。

条件语句if使用技巧

将代码少的逻辑放到if中,而更多的逻辑当成正常系处理,更有利于阅读和理解。

方法

原始代码:

if(condition){
    //中间有100行代码
}else{
    //这里只有1行代码!
};

以上逻辑最好的书写规范是:

if(!condition){
    //1行代码!
    return;
};

//剩余100行代码

案例

原始代码:

selectCategory : function(categoryId, isRedirect) {
    if (categoryId) {
        $('#userPersonasTagDrop .input-group').hide();
        $('#tagSubCategory').addClass('subcategory-not-all').show();
        
        walleUtilStorage.setItem(this.storageLocalCategoryId, categoryId);
        walleUtilStorage.setItem(this.storageLocalTagId, '');
        
        isRedirect      // 比如从收藏夹跳转过来
            ? $('#tagSubCategory span:first').text(this.model.queryParam.tagName)
            : $('#tagSubCategory span:first').text('请选择标签');
        isRedirect || this._getPersonasTagList(categoryId, '', true);
        
    } else {
        $('#userPersonasTagDrop .input-group').show();
        $('#tagSubCategory').hide();
        $('#collectBtn').attr('disabled');
        $('.item-group-search').attr('disabled');
    }
}

优化后:

selectCategory : function(categoryId, isRedirect) {
    //优化1
    if (!categoryId) {
        $('#userPersonasTagDrop .input-group').show();
        $('#tagSubCategory').hide();
        $('#collectBtn').attr('disabled');
        $('.item-group-search').attr('disabled');
        return;
    };
    
    $('#userPersonasTagDrop .input-group').hide();
    $('#tagSubCategory').addClass('subcategory-not-all').show();
    
    walleUtilStorage.setItem(this.storageLocalCategoryId, categoryId);
    walleUtilStorage.setItem(this.storageLocalTagId, '');
    
    //优化2
    if(!isRedirect){
        $('#tagSubCategory span:first').text('请选择标签');
        return;
    };
    
    $('#tagSubCategory span:first').text(this.model.queryParam.tagName)
    this._getPersonasTagList(categoryId, '', true);
}

参考

  • 代码大全,第15章

重复语句for循环化(表驱动法)

代码中发现有太多重复的语句,看似相同,但是又有些不同,于是乎就本能的习惯使用if语句写一大片!

其实最好的做法是代码去重!

核心的思想: 就是想尽一切办法将相似的部分放到一个对象或者数组中,然后循环处理。

示例1

显示一年内各个月的天数。

  • 最low的写法:
function getDaysByMonth(month){
    var days = 0;    
    if(month == 1){
        days = 31;
    }else if(month == 2){
        days = 28; // 不用考虑闰年的情况
    }else if(month == 3){
        days = 31
    }else if(...){
        ...
    };
    return days;
};
  • 采用表驱动法的思路
function getDaysByMonth(month){
    //创建一张表
    var daysAry = [31,28,31,30,31,30,31,31,30,31,30,31];
    return daysAry[month];
};

示例2

原始代码:

if (currentIdx === model.TAB_SYSTEM) { model.searchKeyWd.systemKeyWd = $searchInput.val(); }
if (currentIdx === model.TAB_MODULE) { model.searchKeyWd.moduleKeyWd = $searchInput.val(); }
if (currentIdx === model.TAB_AUTH) { model.searchKeyWd.authKeyWd = $searchInput.val(); }

优化:

var mapper = [{
    key : model.TAB_SYSTEM,
    model : model.searchKeyWd.systemKeyWd
},{
    key : model.TAB_MODULE,
    model : model.searchKeyWd.moduleKeyWd
},{
    key : model.TAB_AUTH,
    model : model.searchKeyWd.authKeyWd
}];

for(var i=0,size=mapper.length;i<size;i++){
    var obj = mapper[i];
    if(currentIdx === obj.key){
        obj.model = $searchInput.val();
    };
};

示例3

原始代码:

function fun1(){
    confirmTodoObj.todo === todoType.SYSTEM_UPDATE && result && result();
    confirmTodoObj.todo === todoType.MODULE_UPDATE && result && result();
    confirmTodoObj.todo === todoType.AUTH_UPDATE   && result && result();
    confirmTodoObj.todo === todoType.SYSTEM_ADD    && result && result();
    confirmTodoObj.todo === todoType.MODULE_ADD    && result && result();
    confirmTodoObj.todo === todoType.AUTH_ADD      && result && result();
}

优化1:

function fun1(){
    if(!result){
        return;
    };
    
    if(confirmTodoObj.todo === todoType.SYSTEM_UPDATE
        || confirmTodoObj.todo === todoType.MODULE_UPDATE
        || confirmTodoObj.todo === todoType.AUTH_UPDATE
        || confirmTodoObj.todo === todoType.SYSTEM_ADD
        || confirmTodoObj.todo === todoType.MODULE_ADD
        || confirmTodoObj.todo === todoType.AUTH_ADD){
    
        result();
    };
}

优化2:

function fun1(){
    if(!result){
    return;
};

switch(confirmTodoObj.todo){
    case todoType.SYSTEM_UPDATE:
    case todoType.AUTH_UPDATE:
    case todoType.SYSTEM_ADD:
    case todoType.MODULE_ADD:
    case todoType.AUTH_ADD:
        result();
        break;
};

最终优化:

function fun1(){
    if(!result){
        return;
    };
    
    var checkKeyList = [
        'SYSTEM_UPDATE',
        'AUTH_UPDATE',
        'SYSTEM_ADD',
        'MODULE_ADD',
        'AUTH_ADD'
    ];
    
    for(var i=0,size=checkKeyList.length; i<size; i++){
        if(confirmTodoObj.todo === todoType[checkKeyList[i]]){
            result();
        };
    };
}

参考

  • 代码大全,第18章

巧用 Array.joinString.split 函数

  • Array.join - 将所有数组或者类数组的元素拼接为一个字符串并返回这个字符串,默认的连接符为 ,
  • String.split - 将一个字符串通过特定的字符串分割为一个数组并返回这个数组,如果不指定分隔符则默认返回一个字符,里面只有一个元素就是当前字符串;

示例

//join的用法

var elements = ['Fire', 'Wind', 'Rain'];

console.log(elements.join()); //expected output: Fire,Wind,Rain
console.log(elements.join('-')); //expected output: Fire-Wind-Rain
//split用法
var elements = 'Jan,Feb,Mar,Apr';

console.log(elements.split());//["Jan,Feb,Mar,Apr"]
console.log(elements.split(','));//["Jan","Feb","Mar","Apr"]
console.log(elements.split(''));//["J", "a", "n", ",", "F", "e", "b", ",", "M", "a", "r", ",", "A", "p", "r"]

案例一

假如后台需要传一个字段,该字段是所有页面上选中的元素的id,通过逗号拼接,如:102,235,356,213

  • 最low的做法
//通过代码将所有元素放到一个数组中
var idAry = [102,235,356,213];

//循环拼接数组
var result = '';
for(var i=0;i<idAry.length;i++){
    result += idAry[i] + ',';
};

//发现最后多了一个逗号,去掉!
result = result.substring(0,result.length-1);
  • 推荐的办法
//通过代码将所有元素放到一个数组中
var idAry = [102,235,356,213];
var result = idAry.join();

案例二

页面需要循环一个数组,动态拼接为html语句 <option> 最后填充到页面上的 <select> 中。

  • 最low的做法
var objAry = [{
    id : 1,
    name : '张三'
},{
    id : 2,
    name : '李四'
}];

var html = '';
for(var i=0;i<objAry.length;i++){
    result += '<option id="'+ objAry[i].id +'">'+ objAry[i].name +'</option>';
};

$('select').html(html);
  • 推荐的办法
var objAry = [{
    id : 1,
    name : '张三'
},{
    id : 2,
    name : '李四'
}];

var html = $.map(objAry,function(d){
    return '<option id="'+ d.id +'">'+ d.name +'</option>';
}).join('');

$('select').html(html);

什么是类数组 Array-Like?

(jQuery)避免手动拼接URL参数

get 请求时,很多人习惯手动拼接url参数,比如:

var queryParam = 'val1='+val1+'&val2='+val2+'&val3='+val3;
var getUrl = url + '?' + queryParam;

推荐使用 jQuery$.param() 方法,或者其它库提供的类似方法。

var queryParam = {
    val1 : val1,
    val2 : val2,
    val3 : val3
};

var getUrl = url + '?' + $.param(queryParam);

详细说明:http://api.jquery.com/jquery.param

(jQuery)对象复制或合并

假如有对象 a 和 对象 b,要实现如下功能:

  1. a 的属性复制到 b 对象上;
  2. ab 合并成新对象 c;

推荐使用 jQuery$.extend() 方法,或者其它库提供的类似方法。

ab 对象分别如下:

var a = {
    apple: 0,
    banana: { 
        weight: 52, 
        price: 100 
    },
    cherry: 97
};

var b = {
    banana: {
        price: 200
    },
    durian: 100
};

目标1:将 a 的属性复制到 b 对象上:

//通过递归的方式,将a对象的所有属性复制到b对象上
$.extend(true, b, a);

//如果不使用递归,而是浅拷贝,则:
$.extend(b, a);

目标2:将 ab 合并成新对象 c;

//通过递归的方式,将a对象的所有属性复制到b对象上
var c = $.extend(true, {}, b, a);

//如果不使用递归,而是浅拷贝,则:
var c = $.extend({}, b, a);

详细说明:http://api.jquery.com/jquery.extend

思考:如果自己实现以上方式,该怎么写?PS:需要考虑深拷贝和浅拷贝的问题;写出来可以与jQuery源码对比下。

三元表达式(Conditional (ternary) Operator)

三元表达式规则:

condition ? expr1 : expr2 

使用三元表达式能简化代码结构,能少写一组 if/else

示例

var str = ture ? 'yes' : 'no';

OR 短路操作符 Short-Circuits

短路操作符规则:

//If exp1 is true then exp2
exp1 || exp2
var a = b || 1;

翻译过来如下:

if(b){
    a = b;
}else{
    a = 1;
};

只所以可以这么写,原因是js是一门弱类型语言,每个变量默认都默认继承一个 true 或者 false 值,称之为:truthy 或者 falsy!
参考:https://www.sitepoint.com/javascript-truthy-falsy/

&& 条件判断

与短路操作类似,还有一种写法如下:

var a = b && 1;

翻译过来如下:

if(b) {
    a = 1;
}else{
    a = b;
};

更多JS中的一些常用的快速写法

  • 获取时间戳
//传统写法
var timestamp = new Date().getTime(); //1512113674165

//快速写法
var timestamp = +new Date(); //1512113674165
  • 浮点数取整
//传统写法
var var1 = parseInt(11.6); //11

//快速写法
var var1 = ~~11.6; //11

//不常用,但是可以
var var1 = 11.6 | 0; //11

位操作符 ~https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT
位操作符 |https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_OR
~~解惑:http://rocha.la/JavaScript-bitwise-operators-in-practice

  • 科学计数法
//传统写法
for(var i=0;i<10000;i++){};

//快速写法
for(var i=0;i<1e4;i++){};
  • 获取随机码
Math.random().toString(16).substring(2); //13位,如:7c4a0278b4509
Math.random().toString(36).substring(2); //11位,如:5b1chmfvhmo
  • 合并两个数组
var a = [1,2,3];
var b = [4,5,6];
Array.prototype.push.apply(a, b);
console.log(a); //[1,2,3,4,5,6]
  • 不增加变量交换两个值
a= [b, b=a][0];
  • 获取数组的最大和最小值
Math.max.apply(Math, [1,2,3]) //3
Math.min.apply(Math, [1,2,3]) //1

推荐书籍

虽然这本书的示例代码都是VB写的,但是思想非常实用,建议大家都看下。

敬请期待

下一篇:提高生产效率的编程思想之抽象能力(二)

@sunmaobin sunmaobin added this to the 2017年 milestone Dec 1, 2017
@sunmaobin sunmaobin self-assigned this Dec 1, 2017
@sunmaobin sunmaobin changed the title 经验分享-提高生产效率的一些编码技巧 经验分享-提高生产效率的一些编码技巧(1) Dec 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant