jQuery基本结构
代码语言:javascript复制<script type="text/javascript">
(function (window,undefind){
var jQuery =function(){
return new jQuery.prototype.init();
}
jQuery.prototype={
constructor:jQuery
}
jQuery.prototype.init.prototype = jQuery.prototype;
window.jQuery=window.$=jQuery;
})(window);
//写完马上被调用
(function test(){
console.log("我要立即执行");
})();
</script>
1.jQuery的本质是一个闭包 2.jQuery为什么要使用闭包来实现? 可以避免多个框架的冲突 3.jQuery如何让外部访问内部定义的局部变量通过 widow.xxx=xxx; 4.jQuery为什么要个自己传入一个实参window 为了后期压缩代码 为了提升查找的效率 5.jQuery为什么要个自己接收一个实参undefind ie9以下的浏览器undefined可以被修改,为了保证内部使用undefined不被修改, 所以需要接受一个正确的undefined
jQuery中的extend方法
jQuery中有众多的方法,但这么多的方法不可能都是一一用每一个函数来封装,因此应用到了extend继承的方法来对这些方法进行管理,不仅起到了封装的效果,并且让代码更好的管理,提高代码的阅读性和维护性。 下面的示例中应用了三种extend方法: 1.通过类调用或添加静态方法 2.通过对象调用或添加实例方法 2.将两种方法合二为一
代码语言:javascript复制<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
function kjQuery(){
}
kjQuery.extend=function(obj){
//此时此刻this就是jQuery这个类
//console.log(this);
for(var key in obj){
this[key]=obj[key];
}
}
kjQuery.extend({
isTest:function(){
console.log("我是Test");
}
});
/*自己理解的原理:kjQuery相当于父类,extend相当于子类,父类调用了子类中的方法
isTest相当于obj,在kjQuery这个类中找到extend方法中key为isTest的值,
而在extend方法中,key为isTest的值为一个函数,返回给this对象
,而this就是kjQuery,就相当于用kjQuery调用了isTest()这个方法
*/
kjQuery.isTest();
//用构造函数prototype来解释,对象添加实例方法
kjQuery.prototype.extend=function(obj){
//此时此刻this就是jQuery这个类
//console.log(this);
for(var key in obj){
this[key]=obj[key];
}
}
var q=new kjQuery();
q.extend({
isDemo:function(){
console.log("我是Demo");
}
});
//此时的extend是kjQuery对象q的方法,不能直接用kjQuery来调用
q.isDemo();
//3.两个方法合二为一
kjQuery.extend = kjQuery.prototype.extend = function(obj) {
for (var key in obj) {
this[key] = obj[key];
}
}
//通过类调用可以添加静态方法
kjQuery.extend({
isDemo0:function(){
console.log("我是类调用的Demo");
}
});
//通过对象调用可以添加实例方法
var q=new kjQuery();
q.extend({
isDemo:function(){
console.log("我是对象调用的Demo");
}
});
q.isDemo()//我是对象调用的Demo
kjQuery.isDemo0();//我是类调用的Demo
</script>
</body>
</html>
jQuery中真伪数组的转换
为了避免浏览器的兼容性,写出了两种完美兼容的互转换方法
代码语言:javascript复制<script type="text/javascript">
$(function() {
var res=document.querySelectorAll("div");
var obj={};
var arr=[1,2,3,4,5,6,7];//真数组
//真数组转伪数组
[].push.apply(obj,arr);
//如果oobj的后面bj里面有值,则会将arr数组里的添加在obj的后面
console.log(obj);
//伪数组转真数组:
//slice是截取字符串的方法
//apply和call方法是往第一个参数对象里添加元素
var arr=[].slice.call(res);
console.log(arr);
});
</script>
jQuery的原生方法和属性的实现(部分)
主要实现了 1.传入 '' null undefind NaN 0 false.返回空的jQuery对象 2.字符串 代码片段:会将创建好的DOM元素储存到jQuery对象中返回 选择器:会将所有找的元素存储到jQuery对象中返回 3.数组 会将数组中的元素依次存入到jQuery对象中返回 4.除上述以外的 会将传入的数据储存到jQuery对象中返回 5.内置静态方法 (1)isString (2)isHTML (3)isObject (4)isWindow (5)isArray (6)isFuncton (7)ready (8)each 6.内置属性方法 (1)push (2)sort (3)splice (4)toArray (5)get (6)eq (7)first (8)last (9)each 7.去除两端空格的方法(兼容浏览器)
原生jQuery代码实现
代码语言:javascript复制/*
1.传入 '' null undefind NaN 0 false.返回空的jQuery对象
2.字符串
代码片段:会将创建好的DOM元素储存到jQuery对象中返回
选择器:会将所有找的元素存储到jQuery对象中返回
3.数组
会将数组中的元素依次存入到jQuery对象中返回
4.除上述以外的
会将传入的数据储存到jQuery对象中返回
*/
(function(window, undefind) {
var kjQuery = function(selector) {
return new kjQuery.prototype.init(selector);
}
kjQuery.prototype = {
constructor: kjQuery,
init: function(selector) {
//去除开头和结尾的空格
selector = kjQuery.trim(selector);
// 1.传入 '' null undefind NaN 0 false.返回空的jQuery对象
if (!selector) {
return this;
}
//2.传入方法:需要先将DOM元素加载完毕
else if (kjQuery.isFuncton(selector)) {
kjQuery.ready(selector);
}
// 2.字符串
// 代码片段:会将创建好的DOM元素储存到jQuery对象中返回
else if (kjQuery.isString(selector)) {
// 代码片段:会将创建好的DOM元素储存到jQuery对象中返回
if (kjQuery.isHTML(selector)) {
// 1.根据代码片段创建所有的元素
var temp = document.createElement("div");
temp.innerHTML = selector;
//优化第二和第三步
[].push.apply(this, temp.children);
} else {
// 选择器:会将所有找的元素存储到jQuery对象中返回
// 1.根据传入的选择器找到对应的元素
var res = document.querySelectorAll(selector);
// 2.将找到的元素添加到kjQuery中
[].push.apply(this, res);
}
}
// 3.数组
// 会将数组中的元素依次存入到jQuery对象中返回
else if (kjQuery.isArray(selector)) {
//不管真伪都将传进来的转化为真数组
var arr = [].slice.call(selector);
// 真数组转化为伪数组
[].push.apply(this, arr);
}
// 4.除上述以外的
// 会将传入的数据储存到jQuery对象中返回
else {
this[0] = selector;
this.length = 1;
}
//把加工以后的返回
return this;
},
//内置属性
jquery: "1.1.0",
selector: "",
length: 0,
//[]找到数组的push方法
//冒号前面的push由jQuery调用
//相当于 [].push.apply(this);
push: [].push,
sort: [].sort,
splice: [].splice,
toArray: function() {
return [].slice.call(this); //将伪数组转化为数组
},
get: function(num) {
// 没有传递参数
if (arguments.length === 0) {
return this.toArray();
}
// 传递不是负数
else if (num >= 0) {
return this[num];
}
// 传递负数
else {
return this[this.length num];
}
},
eq: function(num) {
// 没有传递参数
if (arguments.length === 0) {
return new kjQuery();
} else {
return kjQuery(this.get(num));
}
},
first: function() {
return this.eq(0);
},
last: function() {
return this.eq(-1);
},
each: function(fn) {
return njQuery.each(this, fn);
}
}
kjQuery.extend = kjQuery.prototype.extend = function(obj) {
for (var key in obj) {
this[key] = obj[key];
}
}
//内置方法
kjQuery.extend({
isString: function(str) {
return typeof str == "string";
},
isHTML: function(str) {
return str.charAt(0) == "<" && str.charAt(str.length - 1) == ">" && str.length >= 3;
},
isObject: function(sele) {
return typeof sele == "object";
},
isWindow: function(sele) {
return sele == window;
},
isArray: function(sele) {
if (typeof sele == "object" && "length" in sele && sele != "window") {
return true;
} else {
return false;
}
},
isFuncton: function(sele) {
return typeof sele == "function";
},
ready: function(fn) {
//判断DOM元素是否加载完毕
if (document.readyState == "complete") {
fn();
} else if (document.addEventListener) {
//监听一个事件DOMContentLoaded:这个事件只会等到DOM元素加载完毕后执行回调
document.addEventListener("DOMContentLoaded", function() {
fn();
});
} else {
document.attachEvent("onreadystatechange", function() {
if (document.readyState == "complete") {
fn();
}
});
}
},
each: function(obj, fn) {
// 1.判断是否是数组
if (kjQuery.isArray(obj)) {
for (var i = 0; i < obj.length; i ) {
// var res = fn(i, obj[i]);
var res = fn.call(obj[i], i, obj[i]);
if (res === true) {
continue;
} else if (res === false) {
break;
}
}
}
// 2.判断是否是对象
else if (kjQuery.isObject(obj)) {
for (var key in obj) {
// var res = fn(key, obj[key]);
var res = fn.call(obj[key], key, obj[key]);
if (res === true) {
continue;
} else if (res === false) {
break;
}
}
}
return obj;
}
});
//去除两端空格的方法
kjQuery.trim = function(str) {
if (!kjQuery.isString(str)) {
return str;
}
//判断浏览器是否支持trim方法
if (str.trim) {
return str.trim();
} else {
//匹配开头和结尾的多个空格
return str.replace(/^s |s $/g, "")
}
}
kjQuery.prototype.init.prototype = kjQuery.prototype;
window.kjQuery = window.$ = kjQuery;
})(window);
测试代码
代码语言:javascript复制<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="kjQuery.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<ul>
<li class="item1"></li>
<li class="item2"></li>
<li class="item3"></li>
<li class="item4"></li>
<li class="item5"></li>
</ul>
<script type="text/javascript">
console.log($(""));
console.log($(0));
console.log($("<p>asdas</p><p>asd</p>"));
console.log($(" <div><p>asd</p> </div><p>asd</p> "));
console.log($(".item"));
var arr=[0,2,3,5,6];
var obj={0:"dsas",1:"sad",2:"sad",length:3};
console.log($(arr));
console.log($(obj));
console.log($(123));
console.log($(true));
console.log($().jquery);
$(function(){
var res=$("li");
console.log(res.toArray());
console.log(res.get(1));
// console.log(res.get(-1));
console.log(res.eq(1));
console.log(res.first());
console.log(res.last());
});
var arr = [1, 3, 5, 7, 9];
var obj1 = {0:"lnj",1:"333",2:"male",length:3};
var obj2 = {"name":"lnj","age":"33"};
kjQuery.each(arr, function (key, value) {
console.log(key, value);
console.log(this);
});
</script>
</body>
</html>
感受
jQuery原生代码学起来真的很犯困,学起来也很困难,很多逻辑不理解,但是还是选择了坚持,慢慢的也还好,毕竟是有jQuery的参考源码,虽然现在看的懂的不多,我会相信,有一天我可以完全看懂jQuery源码,并且自己封装出更实用的,适合自己的方法。