使用方式
和JQ
类似,underscore
也占用了一个全局对象;
但是underscore
为用户提供了两种使用方式
_.unique(); // 通过构造函数的静态方法调用
_().unique(); // 通过实例化对象调用其原型链上方法
架构
我们由浅入深,一步步完善
初始架构
首先我们先支持两种调用方式
(function (root) {
// _ 是一个构造函数
var _ = function () {
if(!(this instanceof _)){
return new _();
}
}
_.unique = function(){
console.log(1);
}
_.prototype.unique = function(){
console.log(1);
}
// 挂载到全局
root._ = _;
})(this);
备注:
- 构造函数的
return new _()
和_.prototype.fn
是为第二种方法服务的 - 单纯的用构造函数的静态方法调用其实与直接调用一个用
function
声明的函数无异
通过以上代码我们可以保证两种使用方法都能正常使用
但是这样写引出了新的问题——同一个方法要在静态方法中写一遍,又要在原型链上写一遍,这样做是非常愚蠢的,当里面的方法有上百个的时候整个框架就会很臃肿
我们可以用 混入 来解决这个问题
混入
首先来看看 mixin
这个方法的逻辑
_.mixin = function(obj){
_.each(arr, callback(){
xxx
})
}
解析:
mixin
接收一个参数,这个参数是指要被混入的对象each
用传入的回调函数来对传入数组的每一项进行操作- 在混入这个方法中,
each
的第一个参数arr
应该是被混入对象的静态方法的名字,第二个参数是将具体静态方法混入到_
原型链上的操作 each
这个方法还可以在外部于其他用途被调用,所以第二点和第三点不是讲的完全一样的东西
(function (root) {
var _ = function () {
if(!(this instanceof _)){
return new _();
}
}
_.unique = function(){
console.log(1);
}
// _.prototype.unique = function(){
// console.log(1);
// }
// 对数组的每一项进行操作
_.each = function(arr, cb){
for (var i = 0; i < arr.length; i++) {
cb(arr[i]);
}
}
// 用于将一个对象的静态方法名用数组存储起来并将这个数组返回
_.functions = function(obj){
var resultArr = []