1

背景

should.js是一个比较全的代码测试库,无关框架,引入就可使用,使用起来很方便

使用注意事项和原理浅析

在使用时,引入should.js后,如果你的对象是通过Object.create(null)来创建的,操作如下,该对象.should就不存在
image.png
如果是通过正常的创建对象,就可以使用 .should
image.png

  • 下面说一下为什么会出现这样的问题呢?

首先,用Object.create()来创建对象,会把新创建对象的__proto__指向的对象原型设置为传进Object.create中的对象,比如上面的
let obj2 = Object.create(null)
这里就会把obj2的原型对象设置为null,此时obj2就不能继承基类Object的方法和属性,也就不能使用.should了

  • 那么问题来了,为什么按照这种方式let obj2 = Object.create(null)创建对象就不能使用.should了呢?

这里就需要说一下should.js是如何添加到基类Object中的
首先看一下这段代码
image.png
其中红框中的代码就是如何把should添加到Object中的,这里是通过使用Object.defineProperty来实现的,这也就是为什么上面第一种方式创建的对象不能够.should了,而第二种方式就可以拿到Object的原型上的should

下面我们看一下上图中的should$1是怎么来的
image.png
当然代码中的一些工具方法也会给到should$1,比如:
image.png
这里方法时干什么的就不在这里细说啦,感兴趣的友友们可以自行看下源码哈!
should$1返回了一个Assertion的实例,那么我们看一下Assertion是什么玩意
image.png

Assertion中的方法如下
image.png
在上图Assertion返回的方法中,我们能看到有一个should对象,点开里面还是一个should对象,一层一层嵌套进去,那么它是如何实现should的链式调用的呢?以及它里面的方法时如何添加进去的呢?请看下面这个图:
image.png
在这里有一个addChainf的方法,传入需要name和onCall,这里的name就是需要添加的属性,onCall就是这个属性的描述函数,通过这种方式把should中的方法添加进来,放到should的原型上,后续可以通过原型链的方式调用这些方法。这个方法执行后每次都会返回一个this,就是它本身,因此就实现了should的链式调用。
image.png

小结

  • should里面实现了链式调用,我们上次看的promiz中也实现了链式调用,这两个库实现链式调用还是不一样的,promiz中是在自己的构造函数中返回一个promise属性是自己,而should是通过使用Object.defineProperty的方式直接挂到对象的原型上来实现的,这样做的好处就是基于Object基类的其他类型都可以调用should,比如String、Function、Number等
  • should.js的断言也很语义化,很好理解

辛格
11 声望0 粉丝