在开发过程中,对于某些API在现有的JavaScript运行时环境不支持的时候,我们大都会采用加入polyfill来解决这个问题。但有些时候我们可能需要知道现在某个API到底是否为运行时环境所原生支持,还是polyfill代码支持的。今天在学习Vue 2.X版本的源代码时,就发现了Vue中也有用来检测一个函数是否为运行时原生支持。
function isNative (Ctor) {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
首先,检测要被检测者是否是函数类型,然后会检测这个被检测的函数toString之后的字符串中是否带有native code字眼,如果符合这两个条件,那么说明被检测者是一个当前JavaScript运行时原生支持的函数。
有些人可能会问:为什么要检测这个被检测的函数toString之后的字符串中是否带有native code字眼,当一个对象为JavaScript运行时build-in object (内建对象),并且类型为Function类型时,对其调用toString()方法后,返回的结果字符串就是如下:
"function functionname( ) { [native code] }"
所以我们可以根据这一特性来得出如何去检查一个函数是否为JavaScript运行时环境内建函数。
如 Proxy, Promise, Map, Symbol, Reflect等原生方法,在浏览器中的支持情况都可以用这个函数检测
// 判断浏览器是否支持某一方法
function isNative(Ctor) {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString());
}
console.log(isNative(Proxy)) // true
console.log(isNative(Promise)) // true
console.log(isNative(Map)) // true
console.log(Proxy.toString()) // function Proxy() { [native code] }
console.log(Promise.toString()) // function Promise() { [native code] }
console.log(Map.toString()) // function Map() { [native code] }
对于 Vue.js 的 nextTick
方法,判断是否原生支持 Promise
的目的是为了选择最佳的异步任务调度机制。尽管可以使用 Promise
的 polyfill 来提供对 Promise
的支持,但在某些情况下,原生的 Promise
实现可能会提供更好的性能和可靠性。
原生的 Promise
实现通常是由 JavaScript 引擎提供的,并且经过优化以适应特定的环境和平台。它们通常会利用底层的异步任务调度机制(例如微任务队列)来实现更高效的异步操作。另外,原生的 Promise
实现在不同的浏览器和环境中行为一致,这有助于提供更可靠的跨平台支持。
使用 Promise
的 polyfill 可以在不支持原生 Promise
的环境中提供基本的 Promise
功能,但它可能无法完全模拟原生 Promise
的行为和性能。此外,polyfill 的实现可能会增加额外的代码和复杂性,并且在某些情况下可能存在性能上的损失。
因此,为了提供最佳的性能和可靠性,Vue.js 在 nextTick
方法中首先检查是否原生支持 Promise
,如果支持,则使用原生的 Promise
实现进行异步任务调度。只有在不支持原生 Promise
的情况下,才会回退到使用其他的异步任务调度机制。
这种判断是为了优化 Vue.js 在不同环境下的性能和可靠性,以提供最佳的用户体验。