Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Source Code Reading for Vue 3: How does `hasChanged` work?

Source Code Reading for Vue 3: How does `hasChanged` work?

作者头像
^_^肥仔John
发布于 2021-11-11 06:44:27
发布于 2021-11-11 06:44:27
41700
代码可运行
举报
运行总次数:0
代码可运行

Hey, guys! The next generation of Vue has released already. There are not only the brand new composition API, much more powerful and flexible reactivity system, first-class render function, but also the natural performance with building off the modern browsers.

There have been tens of hundreds of posts and tutorials which are about Vue 3 and source code analysis even. This series is about the source code reading, but includes the related technology explanations. If it's your jam, please stay tune;)

As the first post of this series, it might be nice to nibble a small part of the great Vue 3 pie. hasChanged is used to compare whether a value has changed accounting for NaN, and is leveraged in trigger function to avoid unnecessary effect function re-running, which locates in vue/@shared. And the source code snippet is as below:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export const hasChanged = (value: any, oldValue: any): boolean => {
    return !Object.is(value, oldValue)
}

How simple it is. But what is Object.is?

What is Object.is for?

Object.is method came from ES6 and is capable of determining whether two values are the same. Two values are the same if the one of the following holds:

  1. both undefined
  2. both null
  3. both strings of the same length with the same characters in the same order
  4. both true or both false
  5. both objects reference to the same memory address allocated in heap
  6. both numbers and
    • both -0 or both +0
    • both NaN
    • both non-zero and both not NaN and both have the same value

As we know, loose equality operator(==) applies various coercions to both sides if they are not the same type, before testing for equality. But Object.is doesn't coerce either value.

And the difference between strict equality operator(===) and Object.is is in their treatment of signed zero and NaNs.

NaN a Special Value for Loose and Strict Equality

NaN stands for Not a Number, and the comparison between two NaN value by loose or strict equality will result in false always. We can determine whether a value is NaN by calling x !== x.

However window.isNaN came up from ES5 does us a favor for determining whether a value is type of NaN in some point. But there is a way important and subtle detail that we would ignore. That is doing type conversion before comparison as below

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true
isNaN(null) //false

So when we want to compare whether a value has changed accounting for NaN as Vue 3, we should author as below

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function hasChanged(x, y) {
    x !== y
    && !(typeof x === 'number' && isNaN(x) && typeof y === 'number' && isNaN(y))
}

Since window.isNaN will coerce its argument to type of Number first before comparison, and we have to take some effect to build our own strict isNaN. Fortunately, the so-called strict isNaN Number.isNaN has came up in ES6, and with the help of it, the above code snippet could be simplified into hasChanged = (x, y) => x !== y && !(Number.isNaN(x) && Number.isNaN(y))

Actually we can get the same result without window.isNaN and Number.isNaN in a much leaner manner. Because there is only a possible for a value to not be strictly equal to itself when a value evaluates to NaN.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function hasChanged(x, y) {
    x !== y
    && !(x !== x && y !== y)
}

Strictly Speaking, +0 and -0 are different

As a common sense, +0 and -0 are the same value, but it's not true in JavaScript. For example, the following integer division expression will raise an error in Java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int i = 1;
int positiveZero = +0;

int result1 = i / positiveZero; // raise an ArithmeticException

However, JavaScript is a dynamic type programming language which acts as doing double division as Java for the above example.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1/+0 === 1/0 === Infinity
1/-0 === -Infinity

But +0 and -0 are the same comparing with strict equality operator.

Build your own Object.is

For now, we have known all about the features of Object.is and the differences between it and the loose/strict equality operators. Let's rollup our sleeve to build an own one.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Object.defineProperty(Object, 'is', {
    value(x, y) {
        return x === y
            ? 1 / x === 1 / y // +0 != -0
            : x !== x && y !== y // NaN == NaN
    }
})
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
炫技!JavaScript 的花式玩法
JavaScript 是一个伟大的语言。它有简单的语法,完善的生态系统,更重要的,有一个庞大的社区。
疯狂的技术宅
2019/03/28
1.6K0
炫技!JavaScript 的花式玩法
初学者也能看懂的 Vue3 源码中那些实用的基础工具函数
我们也可以通过ts文件,查看使用函数的位置。同时在VSCode运行调试JS代码,我们比较推荐韩老师写的code runner插件。
用户7108768
2021/09/19
4400
你真的了解浅比较么?
IMWeb前端团队
2018/01/08
1.6K0
初学者也能看懂的 Vue3 源码中那些实用的基础工具函数
写相对很难的源码,耗费了自己的时间和精力,也没收获多少阅读点赞,其实是一件挺受打击的事情。从阅读量和读者受益方面来看,不能促进作者持续输出文章。
若川
2021/09/07
8690
ES6笔记2
一共有3种状态,pending(进行中)、fulfilled(已成功)和rejected(已失败)
小丞同学
2021/08/16
3600
使用ES6新特性开发微信小程序(5)——内建对象的变化
Object对象 Object.prototype.proto:对象具有属性proto,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。 Object.assign(target, …sources):可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。 Object.is(value1, value2)用来判断两个值是否是同一个值。 Object.setPrototypeOf(obj, prototype)将一个
极乐君
2018/02/05
1.4K0
ES6扩展
字符串扩展 str.includes(str):判断是否包含指定字符串,返回true\false str.startWidth(str):判断是否以指定字符开头 str.endWidth(str):判断是否以指定字符结尾 str.repeat(count):重复指定次数 数值扩展 Number.isFinite(i) :判断是否有无限大的数 Number.isNaN(i):判断是否NaN Number.isInteger(i):判断是否为整数 Number.parseInt(str):将字符串转换整数 Ma
切图仔
2022/09/08
1800
ES6基础-ES6的扩展
编辑器(VS Code, Atom,Sublime)或者IDE(Webstorm)
达达前端
2019/11/26
5540
ES6总结
var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。
愤怒的小鸟
2020/12/15
6000
ECMAScript6 基础知识点(上)
ECMAScript 是 JavaScript 的组成部分,它规范了 JS 的语法(解析规则,关键字,语句,声明,操作等)、类型(布尔型,数字,字符串,对象等)、原型和继承、内置对象和函数的标准库(JSON,Math,数组方法,对象内省的方法等等)
Nian糕
2020/05/18
4180
ECMAScript6 基础知识点(上)
JavaScript 新手的踩坑日记
在1995年5月,Eich 大神在10天内就写出了第一个脚本语言的版本,JavaScript 的第一个代号是 Mocha,Marc Andreesen 起的这个名字。由于商标问题以及很多产品已经使用了 Live 的前缀,网景市场部将它改名为 LiveScript。在1995年11月底,Navigator 2.0B3 发行,其中包含了该语言的原型,这个版本相比之前没有什么大的变化。在1995年12月初,Java 语言发展壮大,Sun 把 Java 的商标授权给了网景。这个语言被再次改名,变成了最终的名字——JavaScript。在之后的1997年1月,标准化以后,就成为现在的 ECMAScript。
一缕殇流化隐半边冰霜
2018/08/29
6210
JavaScript 新手的踩坑日记
【ES6+】008-ES6新特性:数值扩展、对象扩展、模块化、Babel代码转换、ES6模块化引入NPM包
EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16;
訾博ZiBo
2025/01/06
1310
【ES6+】008-ES6新特性:数值扩展、对象扩展、模块化、Babel代码转换、ES6模块化引入NPM包
从零开始学 Web 之 ES6(六)ES6基础语法四
在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!
Daotin
2018/09/30
4710
不换的周刊 第41期
在不同的 JavaScript 运行时中显示 API 的兼容性。数据是从 runtime-compat-data 检索的,基于 MDN 的格式。
不换
2024/04/30
870
不换的周刊 第41期
一文快速掌握 es6+新特性及核心语法
接下来我会总结一些工作中常用也比较核心的es6+的语法知识,后面又要慢慢开始工作之旅了,希望在总结自己经验的过程中大家会有所收获~
徐小夕
2019/10/08
9280
一文快速掌握 es6+新特性及核心语法
JavaScript 中的4种相等算法
👆点击“博文视点Broadview”,获取更多书讯 在 JavaScript 中如何判断两个值相等,这个问题看起来非常简单,但并非如此,在 JavaScript 中存在 4 种不同的相等逻辑,如果你不知道他们的区别,或者认为判断相等非常简单,那么本文非常适合你阅读。 ECMAScript 是 JavaScript 的语言规范,在ECMAScript 规范[1]中存在四种相等算法,如下图所示: 上图中四种算法对应的中文名字如下,大部分前端应该熟悉严格相等和非严格相等,但对于同值零和同值却不熟悉,下面我
博文视点Broadview
2023/02/23
5080
JavaScript 中的4种相等算法
每天10个前端小知识 【Day 6】
二分查找,也称为折半查找,是指在有序的数组里找出指定的值,返回该值在数组中的索引。
程序媛夏天
2024/01/18
1750
每天10个前端小知识 【Day 6】
学习尤雨溪写的 Vue3 源码中的简单工具函数
粗略阅读了川哥的文章之后,感觉这期跟上一期不一样。上一期主要学习如何实现某个功能,而这一期主要是学习 Vue3 源码中的工具函数,以及 Vue3 源码的一些调试技巧。虽然看起来偏基础,但我觉得很考验一个程序员的基本功和耐心。
若川
2021/09/07
1.2K0
JavaScript 新手的踩坑日记
在1995年5月,Eich 大神在10天内就写出了第一个脚本语言的版本,JavaScript 的第一个代号是 Mocha,Marc Andreesen 起的这个名字。由于商标问题以及很多产品已经使用了 Live 的前缀,网景市场部将它改名为 LiveScript。在1995年11月底,Navigator 2.0B3 发行,其中包含了该语言的原型,这个版本相比之前没有什么大的变化。在1995年12月初,Java 语言发展壮大,Sun 把 Java 的商标授权给了网景。这个语言被再次改名,变成了最终的名字——JavaScript。在之后的1997年1月,标准化以后,就成为现在的 ECMAScript。
一缕殇流化隐半边冰霜
2024/01/26
1670
JavaScript 新手的踩坑日记
JavaScript数据类型判断
instanceof可以用来判断对象是否是某个类的实例。instanceof的实现原理出门左转查看手撕instanceof
闲花手札
2021/09/08
1K0
相关推荐
炫技!JavaScript 的花式玩法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验