前言
这边就不看undersore的源码了,直接开始源码中的链式调用是怎么完成的
链式调用
先举个例子,暂时先调用去重和map方法
let arr=[1,1,2,2,3,3,4,4,'a','A']
arr.unique(func).map(mapf)
上述代码会在执行完成之后,去重并且返回经过处理的数组,这就是链式调用,而func和mapf则是扩展函数,例如是否区分大小写,按什么标准来处理数组等等
首先用_来表示关键字
调用方式
_.unique(arr, func)
_(arr).unique(func)
上面两行代码说明: _是一个function 因为function 也属于对象,所以符合上述代码的执行方式
获取 _
如下方代码
(function (root) {
var _ = function () {
}
root._ = _
})(this)
先把unique和map方法写上
(function (root) {
var _ = function () {
}
_.map = function (arr, callback) {
return arr.map((item) => {
callback ? callback(itme) : item
})
}
_.unique = function (arr, callback) {
let result = []
arr.forEach((item) => {
let target = callback ? callback(item) : item
if (result.indexOf(target) === -1) {
result.push(target)
}
});
return result
}
root._ = _
})(this)
_.unique(arr, func)
可以发现这种情况下 _.unique(arr, func)
这种方式是可以调用的,用下方代码测试
let arr = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, "a", "A"];
let func = function (key) {
return typeof key === "string" ? key.toLocaleLowerCase() : key;
};
console.log(_.unique(arr, func)); //[1, 2, 3, 4, 5, "a"]
_(arr).unique(func)
但是_(arr).unique(func)
这种方法是无法调用的,_()
这种类似jquery中的无new化实例,后面跟的方法属于原型中的方法,
当_()
时,如果this指向的是window ,此时手动new 一个实例出来,此时想要调用方法,则需要在原型上面定义方法,但是如果像下面代码这样写,这样的话,同一个方法就需要写两遍,这种做法明显是不可取的,
首先,先无new化实例
(function (root) {
var _ = function (obj) {
if (!(this instanceof _)) {
return new _(obj) //无 new 实例
}
this.warp = obj
}
_.prototype.map = function () { }
root._ = _
})(this)
所以需要获取所有的方法,并且遍历到原型里面
return new _(obj)
这里为什么要把obj(调用时传入的数组之类的参数,类似_(arr))作为参数传入进去呢,因为_()
时,内部会调用两次,第一次为执行普通函数,第二次为实例,obj
需要在实例化时获取,所以需要把obj传进去
然后获取到所有方法
_.functions = function (obj) {
let arr = []
for (const key in obj) {
arr.push(key)
}
return arr
}
对每个方法遍历
_.each = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i])
}
}
混入到原型中
_.mixin = function (obj) {
_.each(_.functions(obj), function (key) {
let func = obj[key]
_.prototype[key] = function () {
let args = [this.warp]
Array.prototype.push.apply(args, arguments)
return func.apply(this, args)
}
})
}
_.mixin(_)
这样每一个实例都可以调用原型上的方法
console.log(_(arr).unique(func));//[1, 2, 3, 4, 5, "a"]
下面贴上完整的代码
(function (root) {
var _ = function (obj) {
if (!(this instanceof _)) {
return new _(obj) //无 new 实例
}
this.warp = obj
}
_.map = function (arr, callback) {
return arr.map((item) => {
callback ? callback(itme) : item
})
}
_.unique = function (arr, callback) {
let result = []
arr.forEach((item) => {
let target = callback ? callback(item) : item
if (result.indexOf(target) === -1) {
result.push(target)
}
});
return result
}
_.functions = function (obj) {
let arr = []
for (const key in obj) {
arr.push(key)
}
return arr
}
_.each = function (arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i])
}
}
_.mixin = function (obj) {
_.each(_.functions(obj), function (key) {
let func = obj[key]
_.prototype[key] = function () {
let args = [this.warp]
Array.prototype.push.apply(args, arguments)
return func.apply(this, args)
}
})
}
_.mixin(_)
root._ = _
})(this)
这一篇只是为下一期的链式调用打下了基础,下面一期带来完整的链式调用,如果又错误或者更好的方法,希望大佬提出,谢谢