js规范-变量使用

59 阅读4分钟

变量使用规范

变量使用规范

  • 变量拷贝,需要考虑深浅拷贝

    如果数组或对象只有一层,只需考虑浅拷贝

    
     const sourceObj = {a:1,b:2,c:3}
     const sourceArray = [1,2,3]
    
     bad : ❌
     const targetObj = sourceObj;
     const targetArray = sourceArray;
    
    
     good ✅
     const targetObj = Object.assign({},sourceObj);
     const targeArray  = [...sourceArray]
    

    如果数组或对象有多层,需要考虑深拷贝,并建议使用lodash标准库。
    JSON.stringify实现拷贝,对象中有 new Date, undefined, 函数,NaN,infinityMax 或 infinityMin时存在丢失。

    
    const sourceObj = {a:1,b:2,c:{d:3,e:4}}
    const sourceArray = [1,2,[3,4]]
    
    bad : ❌
    const targetObj = Object.assign({},sourceObj);
    const targetArray = JSON.parse(JSON.stringify(targetArray));
    
    
    good ✅
    import lodash from 'lodash'
    const targetObj = lodash.cloneDeep(sourceObj);
    const targeArray  = lodash.cloneDeep(sourceArray);
    
  • 减少全局变量,通过函数包装
    避免在window上定义,另外也尽量减少var(ESLint约束)

    
       bad : ❌
       window.USERNAME = 'Rebort';     
    
       修改时:
       window.USERNAME = 'John';   
    
       good ✅
       let userNameData = 'Rebort';
       export function userName(){
      	return userNameData;
       }
       export function setUserName(arg){
       	 userNameData = arg;
       }
    
  • 用查询取代临时变量

    临时变量的问题在于:
    它们是暂时的,并且只能在所属函数内使用。因为临时变量只在所属函数内可见,因此,若是不少地方都在用这个临时变量,就会驱使你写出更长的函数。若是把临时变量替换为一个查询,那么其余函数中均可以得到这份信息。

    本例子来源于《重构》,以一个临时变量保存某一表达式的运算结果,若是这个临时变量在多个地方用到,能够考虑用此方法,将表达式提炼到一个独立函数中

    bad :   //有两个临时变量 basePrice、discountFactor
    function getPrice () {
      const basePrice = _quantity * _itemPrice;
      let discountFactor;
      if(basePrice > 100){
          discountFactor = 0.95;
      } else {
          discountFactor = 0.98;
      }
      return basePrice * discountFactor;
    }  
    
    good ✅  //重构后
    function getPrice () {
      return basePrice() * discountFactor();
    } 
    
    function basePrice () {
      return  _quantity * _itemPrice;
    }
    
    function discountFactor () {
       if(basePrice() > 100){
          return 0.95;
      } else {
        return 0.98;
      }
    }
    
  • 对象引用比较,作为参数传递的对象的内存地址,与用于判断相等的对象所引用的内存位置不同

    function checkAge(data) {
       if (data === { age: 18 }) {
         console.log('You are an adult!')
       } else if (data == { age: 18 }) {
         console.log('You are still an adult.')
       } else {
         console.log(`Hmm.. You don't have an age I guess`)
       }
     }
     bad : ❌
    checkAge({ age: 18 });
    //输出 Hmm.. You don't have an age I guess
    
  • 变量提升注意,const/let 块级作用域,var函数作用域
    var有初始化提升,但是let/const没有
    赋值为对象的 const 变量不能再被重新赋值 为其他引用值,但对象的键则不受限制

    bad : ❌
    for (var i = 0; i < 10; ++i) {} console.log(i); // 10
    
    for(var i=0;i< 10;i++){
      setTimeout(function(){
          console.log(i);
      },100)
    }
    // 10次都是输出 10
    
    good ✅
    for (let j = 0; j < 10; ++j) {} console.log(j); // ReferenceError: j 没有定义
    
    for(let i=0;i< 10;i++){
      setTimeout(function(){
          console.log(i);
      },100)
     }
     //输出 0,1,2,3,4,5,6,7,8,9
    
  • this的使用,优先选择箭头函数
    箭头函数没有自己的 this

    bad : ❌
    function Queen() { 
      this.royaltyName = 'Elizabeth';
      // this 引用 window 对象
      setTimeout(function() { console.log(this.royaltyName); }, 1000); 
    }
    new Queen(); // undefined
    
    good:✅
    function King() {
       this.royaltyName = 'Henry';
       // this 引用 King 的实例
       setTimeout(() => console.log(this.royaltyName), 1000);
    }
    new King();  // Henry
    
  • 使用"."来访问对象属性,当访问属性是变量时使用[]

  • 尊重对象所有权,不修改内置对象,如Object Array

    在 JavaScript 中,永远不要污染全局,会在生产环境中产生难以预料的 bug。举个例子,比如你在 Array.prototype 上新增一个 diff 方法来判断两个数组的不同。而你同事也打算做类似的事情,不过他的 diff 方法是用来判断两个数组首位元素的不同。很明显你们方法会产生冲突,遇到这类问题我们可以用 ES2015/ES6 的语法来对 Array 进行扩展。

    
    
      bad : ❌
    
      Array.prototype.diff = function diff(comparisonArray) {
        const hash = new Set(comparisonArray);
        return this.filter(elem => !hash.has(elem));
      };
    
      good ✅
    
      class SuperArray extends Array {
        diff(comparisonArray) {
          const hash = new Set(comparisonArray);
          return this.filter(elem => !hash.has(elem));        
        }
      }
    
  • 使用对象字面量的简写形式和解构赋值

      字面量
      bad : ❌
      let obj = new Object();
    
      good ✅
      let obj = {};
    
      解构赋值:
      let someArray = [1,2,3]
      bad : ❌
      let first = someArray[0];
      let second = someArray[1];
      let third = someArray[2];
    
      good ✅
      let [first,second,third] = someArray;
    
  • 拼接字符串

    bad : ❌
    const name = '小明';
    const score = 59;
    let result = '';
    if(score > 60){
      result = `${name}的考试成绩及格`; 
    }else{
      result = `${name}的考试成绩不及格`; 
    }
    
    good ✅
    
    const name = '小明';
    const score = 59;
    const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
    
  • 使用 可选链?. 和 空位合并运算符

    const person = {
      info: {
        name: 'ricky'
      }
    }
    例如我要获取一个不存在属性
    
    bad : ❌
    const age = person && person.detail && person.detail.age // undefined
    
    good ✅
    // 可选链
    const age = person?.detail?.age // undefined
    

    使用||运算符,只要左边是假值(0、''、false、undefinde、null),就会返回右边的数据
    而??和||最大的区别是,在??这,只有undefined和null才算假值

    const name = 0 || 'ricky' // ricky
    const name = 0 ?? 'ricky' // 0
    
    const name = '' || 'ricky' // ricky
    const name = '' ?? 'ricky' // ''
    
    const name = false || 'ricky' // ricky
    const name = false ?? 'ricky' // false
    
    const name = undefined || 'ricky' // ricky
    const name = undefined ?? 'ricky' // ricky
    
    const name = null || 'ricky' // ricky
    const name = null ?? 'ricky' // ricky
    

URL参数

  • URL参数需要转义
    转义URI组件中的字符 encodeURIComponent()

     bad : ❌
     location.href="https://www.xx.com/a/?url=http://localhost:8081?user=ricky"
    
     good ✅
     location.href=`https://www.xx.com/a/?url=${encodeURIComponent('http://localhost:8081?user=ricky')}`
    
  • URL地址长度不要超过512个字符
    目前公开信息获取的浏览器长度限制是2048,在开发中,低端机型适配中,发现512个字符是个临界值;
    如果比较长的报文,建议跳转的时候,

    1. 以FORM表单的方式提交参数
    2. 后端协商相关信息存储在后端,URL地址只附带ID,后续根据ID查询具体信息
  • URL地址不能包含敏感信息,例如身份证等

  •   bad : ❌
      let url = 'https://www.xx.com/?idCard=310000200001010101'
    
      good ✅
      let url = 'https://www.xx.com/?idCard=310000********0101'
      做脱敏处理或者加密处理