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:

  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

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?的更多相关文章

  1. 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 ...

  2. Memcached source code analysis (threading model)--reference

    Look under the start memcahced threading process memcached multi-threaded mainly by instantiating mu ...

  3. Learning from the CakePHP source code - Part I

    最近开始痛定思痛,研究cakephp的源码. 成长的路上从来没有捷径,没有小聪明. 只有傻傻的努力,你才能听到到成长的声音. 下面这篇文章虽然过时了,但是还是可以看到作者的精神,仿佛与作者隔着时空的交 ...

  4. 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 ...

  5. Troubles in Building Android Source Code

    Some Troubles or problems you may encounter while you setup the Android source code build environmen ...

  6. 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 ...

  7. Website's Game source code

    A Darkroom by doublespeakgames <!DOCTYPE html> <html itemscope itemtype="https://schem ...

  8. 编程等宽字体Source Code Pro(转)

    Source Code Pro - 最佳的免费编程字体之一!来自 Adobe 公司的开源等宽字体下载     每一位程序员都有一套自己喜爱的代码编辑器与编程字体,譬如我们之前就推荐过一款"神 ...

  9. 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 ...

随机推荐

  1. Docker-Compose 容器集群的编排

    Docker-Compose 容器集群的编排 1.Docker-Compose 概述 2.Docker Compose 环境安装 Docker-Compose功能:  可以实现单机上的容器集群编排 1 ...

  2. 洛谷P1563 [NOIP2016 提高组] 玩具谜题

    题目链接:https://www.luogu.com.cn/problem/P1563 哈哈哈,这个题拿来一读是不是很吃惊hahaha,我刚开始读的时候吓了我一跳,这么长的题干,这么绕的题意,还有下面 ...

  3. Java产生指定范围内的随机日期

    要想产生指定范围内的随机日期,首先我们要指定一个范围,那么我们可以通过SImpleDateFormat格式化日期,然后再通过parse()方法设置日期,返回一个Date类型的日期对象,再转化为时间戳( ...

  4. Java中md5摘要算法的几种方法

    public class MD5_Test { public static String md5_1(String oldStr) { char hexDigits[] = { '0', '1', ' ...

  5. nodejs串行有关联

    var async = require('async'); //串行无关联series//串行有关联waterfallasync.waterfall([ function(cb) { setTimeo ...

  6. 理解Python装饰器(Decorator)

    date: 2017-04-14 00:06:46 Python的装饰器,顾名思义就是可以为已有的函数或对象起到装饰的作用,使得达到代码重用的目的. 从一个简单的例子出发 这个例子中我们已经拥有了若干 ...

  7. [LeetCode]13.罗马数字转整数(Java)

    原题地址: roman-to-integer 题目描述: 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M ...

  8. IDA FLIRT使用

    IDA FLIRT/FLAIR   FLIRT是IDA提供的一种函数识别技术,即库文件快速识别与鉴定技术(Fast Library Identification and Recognition Tec ...

  9. MyBatisPlus分页不起作用?因为少了配置

    /** @author QiuQiu&LL @create 2021-09-05 0:25 @Description: / @EnableTransactionManagement @Conf ...

  10. BI工具数据可视化效果哪家强?我选这款!

    BI工具是商业智能(Business Intelligence)软件的英文缩写.目前,商业智能通常被理解为将企业中现有的数据转化为知识,帮助企业做出明智的业务经营决策的工具. 企业经常会为如何选择BI ...