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 ...
随机推荐
- Throwable以及错误
/* 异常的体系: ----------| Throwable 所以异常或者错误类的超类 --------------|Error 错误 错误一般是用于jvm或者是硬件引发的问题,所以我们一般不会通过 ...
- 用代码创建并实例化在storyboard中声明的ViewController
我们的项目最早是基于storyboard开发的,所以一开始所有的ViewController都通过storyboard创建,并通过segue连接跳转 但是今天其中一个controller的view,我 ...
- Linux Ubuntu安装Nvidia多GPU通信库NCCL
0. 前言 在使用Python版本的PaddleDetection进行一些实验时,想同时利用多个GPU提高效率,遇到了一点问题 You may need to install 'nccl2' from ...
- 一个实用批处理指令制作过程分享:Perforce更新完后打开VisualStudio再编译
需求来源 笔者从事Unreal游戏客户端工作,使用VisualStudio开发,然后经常干一个事:就是使用Perforce(或svn)拉取最新代码,(一些时间后)拉取完之后然后打开 项目.sln,即V ...
- 对已有的docker容器增加新的端口映射
一般在运行容器时,我们都会通过参数 -p(使用大写的-P参数则会随机选择宿主机的一个端口进行映射)来指定宿主机和容器端口的映射,例如 docker run -it -d --name [contain ...
- (一)什么是Rabbitmq
1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应. 异步通讯:就像发邮件,不需要马上回复. 两种方式各有优劣,打电话可以立即得到响应,但是你 ...
- erange.heetian.com 回显任意账号
首先获取你想登录ID的REG标识符,例如合天课程专家 获取标识符ba84d3c3-a4a1-4cd2-a00d-2f5722ee86a2 一般用户前缀为REG,这个肯定是管理员之类的= =.. ...
- Spring Boot 启动特别慢的问题
Q:debug模式下代码编译没有问题,本来10 ms左右可以启动的项目,却耗时了3000多ms,why? A:删除项目中的断点,留几个要用的就行. 至于怎么一键删除所有断点,请自行搜索! 一度以为我的 ...
- blender获取任意位置建筑白模
在前端3d可视化开发过程中有时会需要到白模,特别是gis开发,可能会用到各个城市的白模,其实可以使用Blender配合BlenderGis插件来提取osm中的白模.具体步骤如下: 安装软件 在此处下载 ...
- Windows server 2012安装vm-tools遇到的问题
Windows server 2012安装VM tools异常解决办法 在VMWare虚拟机上安装Windows Server 2012之 后安装VMWare Tools时报如下错误信息: 问题:缺少 ...