链模式
解析jQuery
var $ = function () {
return $.fn;
}
$.fn = $.prototype = {
init: function () {}
}
var $ = function (selector) {
return $.fn.init(selector);
}
$.fn = $.prototype = {
init: function (selector) {
this[0] = document.getElementById(selector);
this.length = 1;
return this;
},
length: 0,
size: function () {
return this.length;
}
}
- 覆盖获取
- 之前没次返回的都是同一个对象,会覆盖;
- 使用构造函数, 返回的类型为
$.fn.$.init => $.fn.init
;
- 注意此时返回的
this
就不再指向$.fn
,再设置$.fn.init.prototype = $.fn
;
- 修改构造器:
constructor: $
var $ = function (selector) {
return new $.fn.init(selector);
}
$.fn = $.prototype = {
constructor: $,
init: function (selector) {
this[0] = document.getElementById(selector);
this.length = 1;
return this;
},
length: 0,
size: function () {
return this.length;
}
}
$.fn.init.prototype = $.fn;
- 丰富元素获取
- JS是弱类型语言,并没有纯粹的数组类型,JS引擎的实现也没有做严格校验;一些浏览器解析引擎判断数组时判断
length
属性,能否[索引值]
访问,是否具有些数组方法;
var $ = function (selector, context) {
return new $.fn.init(selector, context);
}
$.fn = $.prototype = {
constructor: $,
init: function (selector, context) {
this.length = 0;
context = context || document;
if (~selector.indexOf('#')) {
this[0] = document.getElementById(selector.slice(1));
this.length = 1;
} else {
var nodeList = document.querySelectorAll(selector);
var len = nodeList.length, i = 0;
for(; i < len; i++) {
this[i] = nodeList[i];
}
this.length = len;
}
this.context = context;
this.selector = selector;
return this;
},
size: function () {
return this.length;
},
//再添加些数组方法,浏览器就会讲返回对象以数组的方式呈现
push: function () {},
sort: function () {},
splice: function () {}
}
$.fn.init.prototype = $.fn;
//扩展方法
$.extend = $.fn.extend = function () {
var i = 1, len = arguments.length,
target = arguments[0], j;
if(i === len) {
//原对象为当前对象í
target = this;
i--;
}
for(; i < len; i++) {
for(j in arguments[i])
target[j] = arguments[i][j]
}
return target;
}
//内部绑定
$.fn.extend({
on: (function () {
//标准DOM2级事件
if(document.addEventListener) {
return function (type, fn) {
var i = this.length - 1;
for(; i >= 0; i--) {
this[i].addEventListener(type, fn, false);
}
return this;
}
} else {
throw new Error('浏览器不支持标准addEventListener方法')
}
})(),
css: function () {
var arg = arguments, len = arg.length;
if(this.length < 1) return this;
if(len === 1) {
if(typeof arg[0] === 'string') {
var name = arg[0], i = 0, l = this.length, results = [];
if(this[0].currentStyle) {
for(; i < l; i++) {
results[i] = this[i].currentStyle[name];
}
} else {
for(; i < l; i++) {
results[i] = getComputedStyle(this[i], false)[name]
}
return results;
}
} else if(typeof arg[0] === 'object') {
for(var i in arg[0]) {
for(var j = this.length - 1; j >= 0; j--)
this[j].style[$.camelCase(i) = arg[0][i]];
}
}
} else if(len === 2) {
for(var j = this.length - 1; j >= 0 ; j--) {
this[j].style[$.camelCase(arg[0])] = arg[1];
}
}
return this;
}
});
//外部绑定
$.extend({
camelCase: function (str) {
return str.replace(/-(w)/g, function (all, letter) {
return letter.toUpperCase();
})
}
});