对于刚开始接触前端开发的朋友们来说,可能地一个令人苦恼的问题是关于运算符 ++ 的计算,特别是它还有前置与后置的区别。当它们和一堆运算在一起的时候,常常令人头晕目眩!

我经常性地称它是一个***难人的问题,因为它本身所发生的操作又是十分的简单——加 1。是的,++ 运算符的唯一计算操作就是给它的操作数加 1。然而,它到底是怎么加的 1 呢?就我而言,我一直都觉得这很神奇,它应该是使用了某种魔法吧!

拨开层层迷雾,在你看见了它的庐山真面目后,你又会惊讶于它是如此的简单纯粹。这一切,都要从最基本的概念——表达式说起。

什么是表达式?表达式是对一个变量或值的引用,或是一组值和变量与运算符的组合。

举例来说,像 1、2 这样的字面值就是一个表达式,尽管它没有多大意义。我们更经常接触的表达式是像 1 + 1 这样的,值与运算符的组合。

表达式的本质是值。分两点来说,一是我们使用表达式的真正目的是要取得它背后的值;二是一个表达式总是会运算并返回一个值。比如,1 + 1 和 2 是等价的,在使用 1 + 1 这个表达式的地方,我们都可以把它换成值 2。这在计算机中之所以成立,是因为 1 + 1 这个表达式它总是会运算并返回值 2。试想一下,如果表达式 1 + 1 没有被计算,它怎么能和值 2 相等呢?

所以,1 + 1 和 2 是等价的准确说法,应该是表达式 1 + 1 的返回值和值 2 是等价的,它们是相等的。尽管前者的概念是表达式,后者的概念是值。

我们再来看一个例子:

let a = 1;
let b = a + 1;

请问这里的变量 b 等于多少?要正确的回答这个问题,你得知道在 a + 1 这个表达式中变量 a 也是一个表达式。所以,我们首先得知道表达式 a 的值是多少,然后将它和 1 相加。表达式和表达式可以通过运算符组合在一起,得到一个新值。这里,表达式 a 的值就是变量 a 引用的值 1。

再来看一个例子:

let a = 1;
let b = (a = 2) + 1;

请问这里的变量 b 又等于多少呢?或者说表达式 (a = 2) + 1 的值是多少?你可能发现了,关键点是要知道表达式 a = 2 的值是多少。

这里就引出了表达式的另一个重要内涵——副作用。表达式的副作用是指表达式在返回值的过程中对别处的值也产生了影响。赋值表达式的副作用就是将某个值赋给了变量,或者说它更换了变量中的值。在 (a = 2) + 1 中,赋值表达式 a = 2 会先给变量 a 赋值 2,然后返回这个变量的值。所以,这里表达式 a = 2 的返回值便就是 2。

有了上面这些概念后,你对前 ++ 和后 ++ 的区别就会有着很好的理解。

这里顺带补充一点,++ 运算符只能和变量一起使用。也就是说,++ 运算符的操作数必须是一个变量,因为它需要一个容器(变量)来承接它的副作用。

前 ++ 和后 ++ 的关键区别就在于它们对操作数执行加 1 的操作的时机点不同。前 ++ 是在返回表达式值之前就对操作数进行了加 1 的运算,后 ++ 则是在返回表达式值之后再对操作数执行加 1 的操作。

举例来说:

let a = 1;
let b = (a++) + 1 + a + (++a) + a + 1;

请问这里的变量 b 又会是等于多少呢?关键点就在 a++ 和 ++a 这两个表达式的值是多少!

a++ 是一个后 ++ 表达式,后 ++ 的副作用发生在它返回表达式值之后。所以,这里 a++ 会先返回表达式 a 的值。所以,这里表达式 a++ 的返回值就是变量 a 的直接引用值 1。

那么紧接在 a++ 后面的那个变量 a 又会是等于多少呢?是 2。因为,前面的 ++ 操作已经给 a 加了 1。所以,这里表达式  (a++) + 1 + a  等价于 1 + 1 + 2。

注意体会这里的操作,这个地方发生且仅发生了两件事:第一件事是返回变量 a 引用的值,第二件事是给变量 a 执行加 1 的运算。这就是为什么后面的 a 会是 2 的原因了,因为这时的 a 已经被加了 1。

++a 是一个前 ++ 表达式,前 ++ 的副作用发生在它返回表达式值之前。也就是说,前 ++ 表达式得到的值是 ++ 运算符执行计算后的结果值。所以,这里表达式 ++a 的值是 3。

所以,这里表达式 (a++) + 1 + a + (++a) + a + 1 等价于 1 + 1 + 2 + 3 + 3 + 1,最终计算结果为 11。

最后,和 ++ 对应的 -- 运算符的运算规则和 ++ 是完全一致的,只不过它的操作是对操作数执行减 1 的运算。

准确理解 JS 的 ++ 运算符的更多相关文章

  1. 从一个简单例子来理解js引用类型指针的工作方式

    <script> var a = {n:1}; var b = a; a.x = a = {n:2}; console.log(a.x);// --> undefined conso ...

  2. js对象详解(JavaScript对象深度剖析,深度理解js对象)

    js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...

  3. 好程序员web前端分享如何理解JS的单线程

    好程序员web前端分享如何理解JS单线程,JS本质是单线程的.也就是说,它并不能像JAVA语言那样,两个线程并发执行. 但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢? 首先,J ...

  4. 10分钟理解JS引擎的执行机制

    首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 (1) JS为什么是单线 ...

  5. 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)

    首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...

  6. 深入理解JS this,作用域

    深入理解JS this 阮一峰博客链接http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html this ...

  7. 【学习笔记】深入理解js原型和闭包(5)——instanceof

    又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...

  8. 【学习笔记】深入理解js原型和闭包(1)—— 一切都是对象

    “一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的运算符——typeof.typeof ...

  9. 理解JS引擎的执行机制

    首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 : JS为什么是单线程的 ...

  10. 深入理解JS引擎的执行机制

    深入理解JS引擎的执行机制 1.灵魂三问 : JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4 ...

随机推荐

  1. WPF中实现弹出进度条窗口

    实现功能: 模拟一个任务开始执行,在窗口弹出一个进度条,展示执行进度,执行完成弹出提示框.例如做数据查询时,如果查询需要一段时间,操作人员可以很好的知道是否查询完成. 1. 设计进度条弹出窗口 进度条 ...

  2. 使用sphinx-book-theme构建文档

    使用sphinx-book-theme构建文档 sphinx-book-theme https://www.sphinx-doc.org/en/master/#confval-language pip ...

  3. 解密prompt系列46. LLM结构化输出代码示例和原理分析

    最近闭源大模型们都陆续支持结构化输出,这一章我们先结合demo看下开源和闭源对结构化输出的支持,随后会介绍Constrained Decoding和Format Restricting Instruc ...

  4. .NET 响应式编程 System.Reactive 系列文章(一):基础概念

    .NET 响应式编程 System.Reactive 系列文章(一):基础概念 引言 在现代软件开发中,处理异步事件和数据流已经成为常见的需求,比如用户输入.网络请求.传感器数据等.这些数据流通常是无 ...

  5. git撤销远已经push到程服务器上某次提交

    git撤销远已经push到程服务器上某次提交 问题: 不小心把一次错误的代码push到远程服务器上的分支上,或者没有merge强制将本地的方法push到git服务器上. 解决方法: 输入 git lo ...

  6. 新格局,新生态!天翼云以国云智算底座赋能AI产业发展!

    近日,中国云产业联盟暨中关村云计算产业联盟(以下简称"云联盟")主办的"首届AIGC全网小程序应用创新大会暨云联盟・移动应用专业委员会成立发布会"在中关村国家自 ...

  7. SQL注入之联合查询注入

    SQL注入之联合查询注入 一.联合查询注入原理 联合查询注入是一种常见的SQL注入攻击手法,其核心原理是利用SQL中的UNION操作符将多个SELECT语句的结果集合并,从而返回一个统一的结果集.在使 ...

  8. MySQL8.0事务知识点

    mysql8.0事务学习 1.基本概念 事务(Transaction)是访问和更新数据库的程序执行单元:是一个最小的不可分割的工作单元,能保证一个业务的完整性:事务中可能包含一个或多个sql语句,这些 ...

  9. 8款支持 C# 语言的 AI 辅助编程神器,高效编程利器!

    前言 在当今这个AI技术日新月异的时代,一股创新的浪潮正席卷着软件开发领域,其中AI辅助编程工具以其独特的魅力脱颖而出,成为了众多开发者不可或缺的得力助手.这些工具不仅能够显著提升开发效率,优化代码质 ...

  10. ABB机器人IO板DSQC651维修检查方法

    ABB机器人作为工业自动化的重要设备,其稳定性和可靠性对于生产线的持续运行至关重要.然而,在实际使用中,由于各种原因,可能会出现ABB机器人IO板DSQC651故障,影响机器人的正常运行. 一.ABB ...