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
}
})

最新文章

  1. 机器学习&数据挖掘笔记_25(PGM练习九:HMM用于分类)
  2. Linux下sysstat工具学习
  3. MongoDB 查询优化分析
  4. Android源码分析之HandlerThread
  5. php 面向对象的方式访问数据库
  6. javaSE第二十六天
  7. var, object, dynamic的区别以及dynamic的使用
  8. 你知道“移动端车牌识别”可以嵌入到PDA中应用吗?
  9. kylin简单优化cube
  10. epoll使用详解
  11. lamp服务器被人恶意绑定域名的解决办法
  12. Spring中BeanFactory与ApplicationContext的区别
  13. http://vjudge.net/contest/view.action?cid=51142#problem/C 精度转换的一道题。。。
  14. 关于oracle分组排序取值的问题
  15. 架构:The Clean Architecture(整洁的架构)(转载)
  16. 解决连锁零售行业IT运维管理四大困境
  17. requestURI的组成部分
  18. $.ajax的一般用法
  19. i++的原子性问题
  20. NoSQL2

热门文章

  1. NSLog输出格式及随机数
  2. CSS网页使用Font Awesome图标字体时,css定义 content 属性
  3. Spring 是怎么处理循环依赖的?
  4. 前端语言之js(对比python快速入门)
  5. LeetCode随缘刷题之无重复字符的最长子串
  6. MATLAB基础学习(2)
  7. 总结haproxy各调度算法的实现方式及其应用场景
  8. 基于XC7Z100+AD9361的双收双发无线电射频板卡
  9. Solution -「LOCAL」Drainage System
  10. 微服务6:通信之网关 Ready