Source Code Reading for Vue 3: How does `hasChanged` work?
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:
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:
- both
undefined - both
null - both
strings of the same length with the same characters in the same order - both
trueor bothfalse - both
objects reference to the same memory address allocated in heap - both
numbers and- both
-0or both+0 - both
NaN - both non-zero and both not
NaNand both have the same value
- both
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
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
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.
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
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.
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.
Object.defineProperty(Object, 'is', {
value(x, y) {
return x === y
? 1 / x === 1 / y // +0 != -0
: x !== x && y !== y // NaN == NaN
}
})
Source Code Reading for Vue 3: How does `hasChanged` work?的更多相关文章
- Tips for newbie to read source code
This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...
- Memcached source code analysis (threading model)--reference
Look under the start memcahced threading process memcached multi-threaded mainly by instantiating mu ...
- Learning from the CakePHP source code - Part I
最近开始痛定思痛,研究cakephp的源码. 成长的路上从来没有捷径,没有小聪明. 只有傻傻的努力,你才能听到到成长的声音. 下面这篇文章虽然过时了,但是还是可以看到作者的精神,仿佛与作者隔着时空的交 ...
- Spring 4 MVC example with Maven - [Source Code Download]
In this tutorial, we show you a Spring 4 MVC example, using Maven build tool. Technologies used : Sp ...
- Troubles in Building Android Source Code
Some Troubles or problems you may encounter while you setup the Android source code build environmen ...
- Finding Comments in Source Code Using Regular Expressions
Many text editors have advanced find (and replace) features. When I’m programming, I like to use an ...
- Website's Game source code
A Darkroom by doublespeakgames <!DOCTYPE html> <html itemscope itemtype="https://schem ...
- 编程等宽字体Source Code Pro(转)
Source Code Pro - 最佳的免费编程字体之一!来自 Adobe 公司的开源等宽字体下载 每一位程序员都有一套自己喜爱的代码编辑器与编程字体,譬如我们之前就推荐过一款"神 ...
- How to build the Robotics Library from source code on Windows
The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...
随机推荐
- JS字符串去替换元素再转换成数组
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11648074.html JS字符串替换不必要的元素, 然后去除多余的空格, 转换成数组: va ...
- 推荐一款仿iPhone桌面的代码. ___王朋.
Demo:https://files.cnblogs.com/files/sixindev/LxGridView-master.zip 这是作者原来的效果图,很多东西还需要慢慢学习.作者用的很多类,根 ...
- DHCP原理与LINUX下的配置
DHCP原理与LINUX下的配置 目录 DHCP原理与LINUX下的配置 一.DHCP工作原理 1.DHCP概述 2.DHCP的优势 3.DHCP的分配方式 (1)自动分配 (2)手动分配 (3)动态 ...
- 数组中包含多个对象 按照对象中的时间进行排序 适用与Angular.js、Jquery、微信小程序等
LiveList.sort(this.compare('StartDate')) //StartData:需要排序的时间 compare: function (property) { ...
- API 接口的安全设计验证:ticket,签名,时间戳
一.背景 1.与前端对接的API接口,如果被第三方抓包并进行恶意篡改参数,可能会导致数据泄露,甚至会被篡改数据 2.与第三方公司的接口对接,第三方如果得到你的接口文档,但是接口确没安全校验,是十分不安 ...
- Solution -「SV 2020 Round I」SA
\(\mathcal{Description}\) 求出处 owo. 给定一个长度为 \(n\),仅包含小写字母的字符串 \(s\),问是否存在长度为 \(n\),仅包含小写字母的字符串 \( ...
- 如何通过pid定位是哪个容器
此时,我有一个pid为28117的进程,通过pdwx命令,无法找到他所在的目录,此时我判定他是docker容器 pwdx 28117 输出如下 28117: / 通过docker ps -q命令,获取 ...
- MySQL架构原理之运行机制
所谓运行机制即MySQL内部就如生产车间如何进行生产的.如下图: 1.建立连接,通过客户端/服务器通信协议与MySQL建立连接.MySQL客户端与服务端的通信方式是"半双工".对于 ...
- 【axios三部曲】一、使用axios
axios作为一个基于promise的网络请求库,它同时支持浏览器和node环境,是我们开发中常用的一个库 它的一些特性: 从浏览器发出XMLHttpRequests 从node.js发出http ...
- kali linux中ifconfig命令不能使用的解决办法
1.安装net-tools,因ifconfig属于net-tools,输入命令: sudo apt-get install net-tools 记住加上sudo哦!4647c21ef50df33a ...