jquery的链式操作,和underscope的链式操作
2020-03-04 本文已影响0人
Mr绍君
先说说jquery的链式操作。
jquey的链式操作比较简单,我们只要把jquery对象返回就可以实现链式调用。
写个最简单的版本。
(function(window) {
jQuery = function(selector) {
return new jQuery.fn.init(selector);
}
jQuery.fn = jQuery.prototype = {
// 先假装传进来的就是id
init: function(selector) {
this.el = document.querySelectorAll(selector)
return this
},
css: function(name, styles) {
if(styles) {
this.el.forEach(element => {
element.style[name] = styles
});
}
return this
}
}
// 共享原型对象
jQuery.fn.init.prototype = jQuery.fn
window.$ = window.jQuery = jQuery
})(this)
我们可以调用一下。
$("#test").css('color', 'red').css('background', '#ccc')
重点说一下underscope的链式调用,这个设计感觉还是挺别致的。
我们先来看一下版本1
(function(window) {
var _ = function() {
}
_.unique = function(arr, cb) {
var ret = []
var target = null
arr.map(item => {
target = cb ? cb(item) : item
if(ret.indexOf(target) === -1) {
ret.push(target)
}
})
return ret
}
_.sort = function(arr, cb) {
return arr.sort(function(x,y) {
return y-x
})
}
window._ = _
})(this)
我们定义一个函数,然后在函数上添加属性。这样我们就可以通过.unique()这样的方式来进行调用。
但是这样并不能实现链式调用。
我们再来看看第二个版本
(function(window) {
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
}
var push = Array.prototype.push
_.unique = function(arr, cb) {
var ret = []
var target = null
arr.map(item => {
target = cb ? cb(item) : item
if(ret.indexOf(target) === -1) {
ret.push(target)
}
})
return ret
}
_.sort = function(arr, cb) {
return arr.sort(function(x,y) {
return y-x
})
}
// 遍历underscope上的所有方法
_.functions = function(obj) {
let names = []
for (const key in obj) {
if (toString.call(obj[key]) === '[object Function]') {
names.push(key)
}
}
return names
}
_.each = function(arr, cb) {
var i=0
if(_.isArray(arr)) {
for(;i<arr.length; i++) {
cb.call(arr, arr[i])
}
} else {
for (const key in arr) {
cb.call(arr, arr[key])
}
}
}
_.isArray = function(obj) {
return toString.call(obj) === '[object Array]';
}
_.chain = function(obj) {
var instance = _(obj);
instance._chain = true;
return instance;
}
_.prototype.value = function() {
return this._wrapped
}
var chainResult = function(instance, obj) {
return instance._chain ? _(obj).chain() : obj;
};
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return chainResult(this, func.apply(_, args));
};
});
};
// Add all of the Underscore functions to the wrapper object.
_.mixin(_);
window._ = _
})(this)
和第一个版本的差异我们定义了一个mixin函数,并且执行了这个函数。
这个函数的作用是遍历对象上的所有属性方法,并把它绑定到原型对象上。这样我们的就变成了一个类对象。
类对象可以进行链式调用,那么数据怎么传递呢?
除了mixin我们还定义了一个chain函数,想要支持链式调用,先调用一下chain函数。
如果参数是_对象,我们就返回,如果不是,我们就把参数传进构造函数,重新进行设置。
这样每次执行方法,都会去prototype原型对象上找对应的函数,并把结果参数重新设置,保证了数据的传递。
console.log(_([1,1,3,3,2,5,4,5]).chain().unique().sort().value())
// [5, 4, 3, 2, 1]