如何在JavaScript中正确处理变量


Posted in Javascript onDecember 25, 2020

变量无处不在。即便我们写一个小函数或一个小工具,也要声明、赋值和读取变量。增强对变量的重视,可以提高代码的可读性和可维护性。

1.建议使用 const,要么使用 let

用 const 或 let 声明自己的 JavaScript 变量。两者之间的主要区别是 const 变量在声明时需要初始化,并且一旦初始化就无法再重新赋值。

// const 需要初始化
const pi = 3.14;
// const 不能被重新赋值
pi = 4.89; 
// throws "TypeError: Assignment to constant variable"

let 声明不需要对值初始化,可以多次重新赋值。

// let 要不要初始化随你
let result;
// let 可被重新赋值
result = 14;
result = result * 2;

const 是一次性分配变量。因为你知道 const 变量不会被修改,所以与 let 相比,对 const 变量的推测比较容易。

声明变量时优先使用 const,然后是 let 。

假设你正在 review 一个函数,并看到一个 const result = ... 声明:

function myBigFunction(param1, param2) {
 /* 一写代码... */

 const result = otherFunction(param1);
 /* 一些代码... */
 return something;
}

虽然不知道 myBigFunction() 中做了些什么,但是我们可以得出结论,result 变量是只读的。

在其他情况下,如果必须在代码执行过程中多次重新对变量赋值,那就用 let。

2. 使变量的作用域最小化

变量位于创建它的作用域中。代码块和函数体为 const 和 let 变量创建作用域。

把变量保持在最小作用域中是提高可读性的一个好习惯。

例如下面的二分查找算法的实现:

function binarySearch(array, search) {
 let middle; let middleItem; let left = 0;
 let right = array.length - 1;

 while(left <= right) {
  middle = Math.floor((left + right) / 2);  
  middleItem = array[middle];  
  if (middleItem === search) { 
   return true; 
  }
  if (middleItem < search) { 
   left = middle + 1; 
  } else {
   right = middle - 1; 
  }
 }
 return false;
}

binarySearch([2, 5, 7, 9], 7); // => true
binarySearch([2, 5, 7, 9], 1); // => false

变量 middle 和 middleItem 是在函数的开头声明的,所以这些变量在 binarySearch() 函数的整个作用域内可用。变量 middle 用来保存二叉搜索的中间索引,而变量 middleItem 保存中间的搜索项。

但是 middle 和 middleItem 变量只用在 while 循环中。那为什么不直接在 while 代码块中声明这些变量呢?

function binarySearch(array, search) {
 let left = 0;
 let right = array.length - 1;

 while(left <= right) {
  const middle = Math.floor((left + right) / 2);  
   const middleItem = array[middle];  
   if (middleItem === search) {
    return true; 
  }
  if (middleItem < search) {
   left = middle + 1; 
  } else {
   right = middle - 1; 
  }
 }
 return false;
}

现在 middle 和 middleItem 只存在于使用变量的作用域内。他们的生命周期极短,所以更容易推断它们的用途。

3. 易于使用

我总是习惯于在函数开始的时候去声明所有变量,尤其是在写一些比较大的函数时。但是这样做会使我在函数中使用变量的意图变得非常混乱。

所以应该在变量声明时应该尽可能靠的近使用位置。这样你就不必去猜:哦,这里声明了变量,但是…它被用在什么地方呢?

假设有一个函数,在函数有包含很多语句。你可以在函数的开头声明并初始化变量 result,但是只在 return 语句中使用了 result:

function myBigFunction(param1, param2) {
 const result = otherFunction(param1); 
 let something;

 /*
  * 一些代码...
  */

 return something + result;}

问题在于 result 变量在开头声明,却只在结尾用到。我们并没有充分的理由在开始的时后就声明这个变量。

所以为了更好地理解 result 变量的功能和作用,要始终使变量声明尽可能的靠近使用它位置。

如果把代码改成这样:

function myBigFunction(param1, param2) {
 let something;

 /* 
  * 一些代码... 
  */

 const result = otherFunction(param1); 
 return something + result;}

现在是不是就清晰多了。

4. 合理的命名

你可能已经知道了很多关于变量命名的知识,所以在这里不会展开说明。不过在众多的命名规则中,我总结出了两个重要的原则:

第一个很简单:使用驼峰命名法,并终如一地保持这种风格。

const message = 'Hello';
const isLoading = true;
let count;

这个规则的一个例外是一些特定的值:比如数字或具有特殊含义的字符串。包特定值的变量通常用大写加下划线的形式,与常规变量区分开:

const SECONDS_IN_MINUTE = 60;
const GRAPHQL_URI = 'http://site.com/graphql';

我认为第二条是:变量名称应该清楚无误地表明是用来保存哪些数据的。

下面是一些很好的例子:

let message = 'Hello';
let isLoading = true;
let count;

message 名称表示此变量包含某种消息,很可能是字符串。

isLoading 也一样,是一个布尔值,用来指示是否正在进行加载。

毫无疑问,count 变量表示一个数字类型的变量,其中包含一些计数结果。

一定要选一个能够清楚表明其作用的变量名。

看一个例子,假设你看到了下面这样的代码:

function salary(ws, r) {
 let t = 0;
 for (w of ws) {
  t += w * r;
 }
 return t;
}

你能很容易知道函数的作用吗?与薪水的计算有关?非常不幸,我们很难看出 ws、 r、 t、 w这些变量名的作用。

但是如果代码是这样:

function calculateTotalSalary(weeksHours, ratePerHour) {
 let totalSalary = 0;
 for (const weekHours of weeksHours) {
  const weeklySalary = weekHours * ratePerHour;
  totalSalary += weeklySalary;
 }
 return totalSalary;
}

我们就很容易知道它们的作用,这就是合理命名的力量。

5.采用中间变量

我一般尽可能避免写注释,更喜欢写出能够自我描述的代码,通过对变量、属性、函数、类等进行合理的命名来表达代码的意图。

如果想使代码本身称为文档,一个好习惯是引入中间变量,这在在处理长表达式时很好用。

比如下面的表达式:

const sum = val1 * val2 + val3 / val4;

可以通过引入两个中间变量来提高长表达式的可读性:

const multiplication = val1 * val2;
const division    = val3 / val4;

const sum = multiplication + division;

再回顾一下前面的二叉搜索算法实现:

function binarySearch(array, search) {
 let left = 0;
 let right = array.length - 1;

 while(left <= right) {
  const middle = Math.floor((left + right) / 2);
  const middleItem = array[middle];  
  if (middleItem === search) {   
   return true; 
  }
  if (middleItem < search) {   
   left = middle + 1; 
  } else {
   right = middle - 1; 
  }
 }
 return false;
}

里面的 middleItem 就是一个中间变量,用于保存中间项。使用中间变量 middleItem 比直接用 array[middle] 更容易。

与缺少 middleItem 变量的函数版本进行比较:

function binarySearch(array, search) {
 let left = 0;
 let right = array.length - 1;

 while(left <= right) {
  const middle = Math.floor((left + right) / 2);
  if (array[middle] === search) {   
   return true; 
  }
  if (array[middle] < search) {   
   left = middle + 1; 
  } else {
   right = middle - 1; 
  }
 }
 return false;
}

没有中间变量的解释,这个版本稍微不太好理解。

通过使用中间变量用代码解释代码。中间变量可能会增加一些语句,但出于增强代码可读性的目的还是非常值得的的。

总结

  • 变量无处不在。在 JavaScript 中使用变量时,首选 const,其次是 let。
  • 尽可能缩小变量的作用域。同样,声明变量时要尽可能靠近其使用位置。
  • 合理的命名是非常重要的。要遵循以下规则:变量名称应该清楚无误地表明是用来保存哪些数据的。不要害怕使用更长的变量名:要追求清晰而不是简短。
  • 最后,最好用代码自己来解释代码。在高度复杂的地方,我更喜欢引入中间变量。

以上就是如何在JavaScript中正确处理变量的详细内容,更多关于JavaScript 处理变量的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
Jan 07 Javascript
JQuery 获得绝对,相对位置的坐标方法
Feb 09 Javascript
jquery提交form表单简单示例分享
Mar 03 Javascript
利用js实现禁止复制文本信息
Jun 03 Javascript
纯JavaScript代码实现文本比较工具
Feb 17 Javascript
判断输入的字符串是否是日期格式的简单方法
Jul 11 Javascript
js动态生成form 并用ajax方式提交的实现方法
Sep 09 Javascript
基于jquery日历价格、库存等设置插件
Jul 05 jQuery
微信小程序支付及退款流程详解
Nov 30 Javascript
vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
Jul 17 Javascript
Vue实现图书管理小案例
Dec 03 Vue.js
Vue和Flask通信的实现
May 19 Vue.js
Vue通过阿里云oss的url连接直接下载文件并修改文件名的方法
Dec 25 #Vue.js
vue使用require.context实现动态注册路由
Dec 25 #Vue.js
vue 使用rules对表单字段进行校验的步骤
Dec 25 #Vue.js
vue 实现基础组件的自动化全局注册
Dec 25 #Vue.js
vue 使用class创建和清除水印的示例代码
Dec 25 #Vue.js
React中使用Vditor自定义图片详解
Dec 25 #Javascript
基于vue+echarts数据可视化大屏展示的实现
Dec 25 #Vue.js
You might like
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
yii2中的rules 自定义验证规则详解
2016/04/19 PHP
PHP实现批量删除(封装)
2017/04/28 PHP
PHP文件后缀不强制为.php方法
2019/03/31 PHP
实例分析10个PHP常见安全问题
2019/07/09 PHP
封装好的省市地区联动控件附下载
2007/08/13 Javascript
javascript 密码强度验证规则、打分、验证(给出前端代码,后端代码可根据强度规则翻译)
2010/05/18 Javascript
js中查找最近的共有祖先元素的实现代码
2010/12/30 Javascript
jQuery.validate 常用方法及需要注意的问题
2013/03/20 Javascript
JavaScript实现继承的4种方法总结
2014/10/16 Javascript
jQuery滚动加载图片实现原理
2015/12/14 Javascript
AngularJS基础 ng-if 指令用法
2016/08/01 Javascript
微信小程序 setData使用方法及常用错误解决办法
2017/05/11 Javascript
加载 vue 远程代码的组件实例详解
2017/11/20 Javascript
JS实现二维数组横纵列转置的方法
2018/04/17 Javascript
利用原生的JavaScript实现简单拼图游戏
2018/11/18 Javascript
JavaScript实现页面中录音功能的方法
2019/06/04 Javascript
什么时候不能在 Node.js 中使用 Lock Files
2019/06/24 Javascript
js生成1到100的随机数最简单的实现方法
2020/02/07 Javascript
JavaScript进阶(三)闭包原理与用法详解
2020/05/09 Javascript
React倒计时功能实现代码——解耦通用
2020/09/18 Javascript
利用Python的Django框架生成PDF文件的教程
2015/07/22 Python
Python3 Tkinter选择路径功能的实现方法
2019/06/14 Python
简单了解python反射机制的一些知识
2019/07/13 Python
使用CSS Grid布局实现网格的流动
2014/12/30 HTML / CSS
关于webview适配H5上传照片或者视频文件的方法
2020/11/04 HTML / CSS
如何用JQuery进行表单验证
2013/05/29 面试题
行政总经理岗位职责
2013/12/05 职场文书
实习单位接收函模板
2014/01/10 职场文书
继承权公证书
2014/04/09 职场文书
项目申报专员岗位职责
2014/07/09 职场文书
教师党员自我评价范文
2015/03/04 职场文书
争做文明公民倡议书
2019/06/24 职场文书
MySQL Router的安装部署
2021/04/24 MySQL
一文搞懂MySQL索引页结构
2022/02/28 MySQL
vue数据字典取键值项目的字典问题
2022/04/12 Vue.js