一道JS题,让我更深刻的理解了JS的执行机制

简介: 闲逛摸鱼发现一道有趣的题,题目如下,本来是不想拿出来单独写一篇文章的,因为太短了,但是我需要存在感,沸点没人看,所以还是写一篇文章吧;

闲逛摸鱼发现一道有趣的题,题目如下:

let i = 0;

function x() {
   
   
    i++;
    return 10;
}

i += x();
console.log(i) // 10 or 11

这道题我发沸点了,本来是不想拿出来单独写一篇文章的,因为太短了,但是我需要存在感,沸点没人看,所以还是写一篇文章吧;

原沸点在这里:https://juejin.cn/pin/7169568535033675784

题目分析

题目很简单,有效代码只有6行,按照流程分析一下:

  1. 声明变量 i,赋值为 0
  2. 声明函数 x,函数内部 i 自增,返回 10
  3. i 加等于 x 的返回值

结束,这个时候 i 的值是 10 还是 11 呢?可以在浏览器中执行一下;

答案是:10

为什么是 10

js的代码执行大家都知道是从上到下,从左到右的(排除异步、回调等),然后还有一些特殊的情况,比如函数声明提升、变量提升等,操作符的优先级等等,这些就不在这里讲了;

这道题的关键在于函数x内部执行了一个i++,下面又有一个i += x(),这里需要将执行过程拆解一下:

  1. 定义变量 i,赋值为 0
  2. 定义函数 x
    1. i 自增
    2. 返回 10
  3. i 加等于 x 的返回值
    1. i += x()
    2. i = i + x()
    3. i = 0 + x()
    4. i = 0 + 10
    5. i = 10

看到这里应该就了解为什么是 10 了,因为js的执行机制是从左到右;

i += x()最终会被解释为i = i + x(),从左到右执行,是先取出i的值,然后再执行x()

i不是一个引用类型,所以是直接拿到i的值0再执行x()x()内部执行的i++并不会影响到已经获取到的i的值,所以最终的结果是10

怎么让结果是 11

上面讲到了js的执行是从左到右的,我们只需要i的取值在x()执行之后就可以了,如下:

let i = 0;

function x() {
   
   
    i++;
    return 10;
}

i = x() + i;
console.log(i) // 10 or 11

这样就可以了,因为i的取值是在x()执行之后,所以i的值是1,最终结果就是11了;

解惑

上面讲的是这道理的整体运作原理和流程,不能我说i += x()最终解释的结果就是i = i + x(),但是事实就是如此,下面截图来自MDN 表达式与运算符

image.png

可以看到最终的解释就是如此,从这里可以看到上面解题的分析是正确的,+=运算符可能就是一个语法糖,最后让结果变成11又引发我一个问题。

以前有一道题是这样的,如何让a === 1 && a === 2 && a === 3成立,那么我改造一下,成为下面这种形式是否也是可以的呢?代码如下:

var a = 1;
var result = a++ === 1 && a++ === 2 && a++ === 3;
console.log(result);

或者现这种形式:

var a = 0;
var result = ++a === 1 && ++a === 2 && ++a === 3;
console.log(result);

上面这两种形式,最终result的结果都是true,感兴趣可以在控制台输出看看,非常有趣。

总结

确实是一道有趣的题,让我对js的执行机制有了更深的理解,用这道题分析简单的分析了一下js的执行机制,js的执行机制是自上而下,从左往右,内部会将一些语法进行拆解,对于非引用类型取值之后,取值的地方就固定了,不会发生修改。

目录
相关文章
|
2月前
|
设计模式 JavaScript 前端开发
深入理解 JavaScript 中的绑定机制(下)
深入理解 JavaScript 中的绑定机制(下)
|
2月前
|
JavaScript 前端开发
深入理解 JavaScript 中的绑定机制(上)
深入理解 JavaScript 中的绑定机制(上)
|
2月前
|
前端开发 JavaScript UED
深入理解JavaScript中的事件循环机制
JavaScript中的事件循环机制是其异步编程的核心,深入理解该机制对于开发高效、流畅的前端应用至关重要。本文将介绍事件循环的工作原理、常见的事件循环模型,以及如何利用这些知识解决前端开发中的常见问题。
|
13天前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
24 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
|
2月前
|
缓存 移动开发 JavaScript
WKWebView对网页和js,css,png等资源文件的缓存机制及如何刷新缓存
WKWebView对网页和js,css,png等资源文件的缓存机制及如何刷新缓存
48 1
|
20天前
|
JavaScript 前端开发
深入解析JavaScript中的面向对象编程,包括对象的基本概念、创建对象的方法、继承机制以及面向对象编程的优势
【6月更文挑战第12天】本文探讨JavaScript中的面向对象编程,解释了对象的基本概念,如属性和方法,以及基于原型的结构。介绍了创建对象的四种方法:字面量、构造函数、Object.create()和ES6的class关键字。还阐述了继承机制,包括原型链和ES6的class继承,并强调了面向对象编程的代码复用和模块化优势。
25 0
|
2月前
|
开发框架 JavaScript 前端开发
JavaScript的事件循环机制是其非阻塞I/O的关键
【5月更文挑战第13天】JavaScript的事件循环机制是其非阻塞I/O的关键,由调用栈、事件队列和Web APIs构成。当异步操作完成,回调函数进入事件队列,待调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、游戏逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中则常使用游戏框架进行抽象处理。
49 4
|
2月前
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包机制
闭包是JavaScript中一个重要且常被误解的概念。本文将深入探讨闭包的本质、工作原理以及在实际开发中的应用。通过详细解析闭包的定义、作用域链、内存管理等方面,读者将对闭包有更清晰的理解,并能够运用闭包解决实际开发中的问题。
|
2月前
|
前端开发 JavaScript UED
JavaScript 的事件循环机制是其非阻塞 I/O 模型的核心
【5月更文挑战第9天】JavaScript的事件循环机制是其非阻塞I/O的关键,通过单线程的调用栈和任务队列处理异步任务。当调用栈空时,事件循环从任务队列取出一个任务执行,形成循环。异步操作完成后,回调函数进入任务队列,等待被事件循环处理。微任务如Promise回调在每个宏任务结束后执行。此机制确保JavaScript能高效处理异步操作,不阻塞主线程,提供流畅的用户体验。
25 2