本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
学习目标
Vue2 源码 shared 模块中的几十个实用工具函数
JavaScript 的一些基础知识
源码地址
- 看文章:初学者也能看懂的 Vue2 源码中那些实用的基础工具函数
- 在线vscode 查看 github1s.com/vuejs/vue/b…
源码解读
本文为个人笔记,记录一些笔者觉得不太熟悉和有必要记录的函数和知识点。
isPromise 判断是否是 promise
function isDef (v) {
return v !== undefined && v !== null
}//判断是否定义
function isPromise (val) {
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function'
)
}
// 例子:
// 判断是不是Promise对象
const p1 = new Promise(function(resolve, reject){
resolve('若川');
});
isPromise(p1); // true
cached 缓存
/**
* Create a cached version of a pure function.
*/
function cached (fn) {//cached方法接收参数fn函数,该函数用于处理存储的键值;
var cache = Object.create(null);
return (function cachedFn (str) {//该方法返回值是函数,形成了闭包,返回的函数接收参数str,作为存取数据的键名
var hit = cache[str];//
return hit || (cache[str] = fn(str))//执行返回值函数时,根据str参数从cache这个存储对象中获取对应的键值,如果获取不到,则对该数据进行存储,并返回键值,实现存和取功能一体
})
}
利用闭包的特性,创建了一个定制缓存数据的函数,同时为了性能等考虑,采用了Object.create,即存储数据的缓存对象是一个干干净净的对象,不会继承Object的一些方法。
分析:
配合示例食用:
// 将连字符为大驼峰
var camelize = cached(function (str) {
return str.replace(/-(\w)/g, function (_, c) {
return c ? c.toUpperCase() : ''
})
});
camelize('border-radius') // 'borderRadius'
以上代码执行 cached 后返回的 camelize 每次执行的参数都会被 cached 的参数执行,并且缓存在 hit 中。
因此如果我们要处理一个字符串,将其由连字符的形式变为大驼峰。对于可能要多次操作相同的字符串,最好的方法就是第一次处理完后将这个字符及结果缓存起来。下次再遇到执行读取操作要比再次执行字符串方法更加快速。
扩展:闭包
JavaScript 闭包的本质源自两点,词法作用域和函数当作值传递。
词法作用域,就是,按照代码书写时的样子,内部函数可以访问函数外面的变量。引擎通过数据结构和算法表示一个函数,使得在代码解释执行时按照词法作用域的规则,可以访问外围的变量,这些变量就登记在相应的数据结构中。
函数当作值传递,即所谓的first class对象。就是可以把函数当作一个值来赋值,当作参数传给别的函数,也可以把函数当作一个值 return。一个函数被当作值返回时,也就相当于返回了一个通道,这个通道可以访问这个函数词法作用域中的变量,即函数所需要的数据结构保存了下来,数据结构中的值在外层函数执行时创建,外层函数执行完毕时理因销毁,但由于内部函数作为值返回出去,这些值得以保存下来。而且无法直接访问,必须通过返回的函数。这也就是私有性。
function outer(){
let local = 2;
function inner () {
return local;
}
return inner;
}
let fn = outer();
console.log(fn()); //2
在上面的例子中,outer函数内部定义了inner函数,然后将inner函数对象作为值返回了。之后执行了outer函数。实际上,就将inner函数赋值给了fn全局变量。在outer执行之后,在JS中outer函数的作用域会被销毁,因为引擎有垃圾回收器用来释放不再使用的内存空间。
因为这里将函数作为值返回了,产生了闭包。而正因为闭包的存在,我们仍然能访问到local局部变量,所以outer的词法作用域依然存在。因此也就证明了闭包可以访问所在的词法作用域,且拥有更长的生命周期,保持对当前词法作用域的引用。
学习收获
通过本期的学习,了解了一些工具函数,不过对于这些工具函数的使用场景还是不太了解,需要以后的加强学习,通过对源码的阅读,学习相关知识,加强了自己的JavaScript基础。后续仍要坚持学习,加油~