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. NS前缀

    NS来自于NeXTStep的一个软件 NeXT Software OC中不支持命名空间(namespace) NS是为了避免命名冲突而给的前缀 看到NS前缀就知道是Cocoa中的系统类的名称

  2. 关于增强for循环的使用

    1 class MultipleQUestion extends Question{ //多选题类 2 3 private char[] answer; //多选题答案属性 4 5 public ch ...

  3. 枚举和注解@override、@Deprecated、@SuppressWarnings

    一.枚举 简介: 1)枚举对应英文(enumeration,简写 enum) 2)枚举是一组常量的集合. 3)可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象. 实现方式: 1.自定 ...

  4. CSS解决父级边框坍塌的问题

    1. 浮动元素后面增加空的div 首先在父级标签内添加如下<div>标签 <div id="clear"></div> 然后在CSS中对该标签进 ...

  5. Solution -「多校联训」最大面积

    \(\mathcal{Description}\)   Link.   平面上有 \(n\) 个点 \(A_{1..n}\),\(q\) 次询问,每次给出点 \(P\),求 \[\max_{1\le ...

  6. set和setenv

    今天用set设置PATH变量(加一个路径),发现虽然echo的时候显示修改成功了,实际执行命令的时候确没有去那个路径查找:当前shell是c shell(csh). 在网上找了一些材料,总结如下:   ...

  7. .NET CORE 鉴权

    基础信息 1.什么是鉴权授权? 鉴权是验证用户是否拥有访问系统的权利,授权是判断用户是否有权限做一些其他操作. 2.传统的Session 和Cookie 主要用于无状态请求下的的用户身份识别,只不过S ...

  8. 都 2022 了,还不抓紧学 typeScript ?

    Hi,我是前端人,今日与君共勉! 本篇文章主要介绍的是什么是 typeScript ? typeScript 与 javaScript 有什么关系呢?我们为什么要学习 typeScript ? 一.什 ...

  9. [Matlab]三维曲面绘制实例

    [x,y] = meshgrid(-8:0.5:8); z = sin(sqrt(x.^2+y.^2))./sqrt(x.^2+y.^2+eps); subplot(2,2,1); mesh(x,y, ...

  10. IP网络主动测评系统

    一.IT网络运维面临的挑战 1. 网络性能可视化 • 与公有云和SaaS平台连接的可靠性 • 广域网线路性能 • 互联网专线性能 2.诊断工具 • 现场无IT工程师覆盖 • 诊断的人力费用 • 网络与 ...