如何在JavaScript中正确处理变量

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

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 处理变量的资料请关注我们其它相关文章!

(0)

相关推荐

  • nuxt.js添加环境变量,区分项目打包环境操作

    最近由于业务需求,开发了一个nuxt.js项目. 配置打包环境变量时,发现nuxt.js的文档过于简单,无法做参照. 经查证了一些资料后,解决了该问题.遂整理成文档,发布于此,给同行一些参照. 一.添加cross-env插件 npm npm i cross-env yarn yarn add cross-env 二.添加环境变量文件 根目录添加env.production NODE_ENV = 'production' VUE_APP_TITLE = 'production' 根目录添加env.

  • JS如何定义用字符串拼接的变量

    今天在写js的时候碰到了难题,我又一个页面需要生成很多的变量.但是变量的名称是根据参数的不同而区分的. 例如可能需要生成 date_1,date_2,datet_3... (后面的数字是根据参数来的). 所以我的函数名 应该由 var name = "test_"+num; 生成函数名 但这问题就来了. 1可以使用 window[name] = " " 这种方式来定义变量: 所以 var "test_"+num = 100; 这中肯定是错误的.后

  • ASP.NET Core根据环境变量支持多个 appsettings.json配置文件

    一.背景 在项目开发的过程当中,开发环境与生产环境的配置肯定是不一样的.拿个最简单的例子来说,比如连接字符串这种东西,开发环境肯定不能连生产数据库.在之前的话,这种情况基本靠准备两个同名的配置文件来进行处理,然后你在本地就使用本地的配置文件,生产环境就使用生产环境的配置文件,十分麻烦. ASP.NET Core支持利用环境变量来动态配置 JSON 文件,下面就来看一下如何在项目中使用这样功能吧. 二.准备工作 ASP.NET Core在应用启动时读取环境变量ASPNETCORE_ENVIRONM

  • JavaScript 中判断变量是否为数字的示例代码

    简介 JavaScript 是一种动态类型语言,这意味着解释器在运行时确定变量的类型.实际上,这也允许我们在相同的代码中使用相同的变量来存储不同类型的数据.如果没有文档和一致性,我们在使用代码时并不总是知道变量的类型. 当我们期望一个变量是数字时,对字符串或数组进行操作可能会在代码中导致奇怪的结果.在本文中,我们将会介绍一些判断变量是否为数字的函数. 像"10"之类的数字的字符串不应被接受.在JavaScript中,诸如NaN,Infinity和-Infinity之类的特殊值也是数字类

  • JS中准确判断变量类型的方法

    这是一个高频面试题,我们开发中也进程会遇到,今天我们来实现一个函数getValType(val)用来获取一个变量的类型.从1. JS基础变量类型.2. Js中判断变量的函数. 3. 实现getValType函数.3个方面来分析实现. Js基础变量类型 在 JS 中,有 5 种基本数据类型和 1 种复杂数据类型,基本数据类型有:Undefined, Null, Boolean, Number和String:复杂数据类型是Object,Object中还细分了很多具体的类型,比如:Array, Fun

  • three.js着色器材质的内置变量示例详解

    什么是着色器? 固定渲染管线: --标准的几何&光照(T&L)管线,功能是固定的,它控制着世界.视.投影变换及固定光照控制和纹理混合.T&L管线可以被渲染状态控制,矩阵,光照和采制参数.如果有了固定渲染管线,编写程序就比较容易了,因为所有的变换都是由固定渲染管线来完成的,但是缺点就是自由度低.固定渲染管线只能完成一些最基本的操作,如果想要做一些特殊的处理,就比较麻烦了. 可编辑渲染管线:--WebGL中不存在固定渲染管线,坐标变换必须全部由自己来做,这个记述了坐标变换的机制就叫做着

  • JS变量提升及函数提升实例解析

    1在js中只有两种作用域 a:全局作用域 b:函数作用域 在ES6之前,js是没有块级作用域. 首先来解释一下什么是没有块级作用域? 所以此时 是可以打印输出变量a的值. 2:什么是变量提升? 在我们的js中,代码的执行时分两步走的,1.预解析 2.一步一步执行 在预解析阶段:首先会在全局作用域内,js解析器会找所有的 var .function .参数,并提前到当前作用域的最顶上去(变量的赋值操作不会提前,还在原来的地方),此时并没有执行代码. 然后再开始一行一行执行代码.遇到了函数调用,于是

  • JS中作用域以及变量范围分析

    变量作用域 js作为一门脚本语言,他与c,java这些语言是不相同的. 全局变量 在js中声明全局变量,有下面几种方式: 1.在函数外通过var来声明. var test ="hello"; console.log(test); function a(){ test="xx"; console.log(test); } a(); console.log(test); 结果: hello xx xx 这种方式通过声明的变量在任何地方都可进行修改和使用. 2.在函数中隐

  • Javascript新手入门之字符串拼接与变量的应用

    1. 课程大纲 字符串拼接(+)的学习和应用 坐标变换在飞机大战游戏中的应用 2.1 字符串的拼接 在JS中使用"+"号,连接字符串.变量.数值等. 2.2 在警告框上显示朋友的数量 在警告框上显示朋友的数量,显示效果如下 声明变量 friends表示朋友的数量,在警告框上显示"我的朋友数量为:7",使用字符串拼接符"+" ,代码如下' var friends = 7; alert("我的朋友数量为:" +friends);

  • JavaScript中变量提升和函数提升的详解

    第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函数提升 3. 为什么要进行提升 4. 最佳实践 那么,我们就开始进入主题吧. 1. 变量提升 通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理.(注:当前流行的JS引擎大都对源码进行了编译,由于引擎的不同,编译形式也会有

随机推荐