jQuery原理
今天手动实现了以下方法
jQ原型上的核心方法和属性:
1、jquery 获取jQ版本号
2、selector 实例默认的选择器取值
3、length 实例默认的长度
3、push 给实例添加新元素
4、sort 对实例中的元素进行排序
5、splice 按照指定下标指定数量删除元素,也可以替换删除的元素
6、toArray 把实例转换为数组返回
7、get 获取指定下标的元素,获取的是原生DOM
6、eq 获取指定下标的元素,获取的是jQuery类型的实例对象
7、first 获取实例中的第一个元素,是jQuery类型的实例对象
8、last 获取实例中的最后一个元素,是jQuery类型的实例对象
9、each 遍历实例,把遍历到的数据传给回调使用
10、map 遍历实例,把遍历到的数据传给回调使用,然后把回调的返回值收集起来组成一个新的数组返回
jQuery的extend方法
<!--
* @Author: 码小余
* @Date: 2020-06-24 10:33:33
* @LastEditTime: 2020-06-24 10:40:02
* @FilePath: \代码\jQuery原理\04-jQuery的extend方法.html
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>04-jQuery的extend方法</title>
<script>
function njQuery() {}
/*
njQuery.extend = function (obj) {
// 此时此刻的this就是njQuery这个类
// console.log(this);
for (var key in obj) {
// njQuery["isTest"] = function () {console.log("test");}
this[key] = obj[key];
}
};
njQuery.extend({
isTest: function () {
console.log("test");
},
});
njQuery.isTest();
*/
/*
njQuery.prototype.extend = function (obj) {
// 此时此刻的this是njQuery对象
// console.log(this);
for (var key in obj) {
// q["isDemo"] = function () {console.log("demo");}
this[key] = obj[key];
}
};
var q = new njQuery();
q.extend({
isDemo: function () {
console.log("demo");
},
});
q.isDemo();
*/
// 合并
njQuery.extend = njQuery.prototype.extend = function (obj) {
// console.log(this);
for (var key in obj) {
this[key] = obj[key];
}
};
// njQuery.extend({});
var q = new njQuery();
q.extend({});
</script>
</head>
<body></body>
</html>
jQuery监听DOM加载
<!--
* @Author: 码小余
* @Date: 2020-06-24 11:25:38
* @LastEditTime: 2020-06-24 11:26:15
* @FilePath: \代码\jQuery原理\05-jQuery监听DOM加载.html
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="js/njQuery-1.0.0.js"></script>
<script>
/*
onload事件会等到DOM元素加载完毕, 并且还会等到资源也加载完毕才会执行
DOMContentLoaded事件只会等到DOM元素加载完毕就会执行回调
*/
/*
window.onload = function (ev) {
// var res = document.querySelectorAll("div");
// console.log(res);
console.log("onload");
}
document.addEventListener("DOMContentLoaded", function () {
// var res = document.querySelectorAll("div");
// console.log(res);
console.log("DOMContentLoaded");
});
*/
/*
document.readyState属性有如下的状态
uninitialized - 还未开始载入
loading - 载入中
interactive - 已加载,文档与用户可以开始交互
complete - 载入完成
onreadystatechange事件就是专门用于监听document.readyState属性的改变的
*/
/*
document.attachEvent("onreadystatechange", function () {
if(document.readyState == "complete"){
console.log("onreadystatechange");
}
});
*/
$(function () {
var res = document.querySelectorAll("div");
console.log(res);
});
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>
代码记录:
/*
* @Author: 码小余
* @Date: 2020-06-23 09:26:25
* @LastEditTime: 2020-06-24 13:30:21
* @FilePath: \代码\jQuery原理\js\njQuery-1.1.0.js
*/
(function (window, undefined) {
function njQuery(selector) {
return new njQuery.prototype.init(selector);
}
njQuery.prototype = {
constructor: njQuery,
init: function (selector) {
/*
1.传入 '' null undefined NaN 0 false, 返回空的jQuery对象
2.字符串:
代码片段:会将创建好的DOM元素存储到jQuery对象中返回
选择器: 会将找到的所有元素存储到jQuery对象中返回
3.数组:
会将数组中存储的元素依次存储到jQuery对象中立返回
4.除上述类型以外的:
会将传入的数据存储到jQuery对象中返回
*/
// 0. 去除字符串两端的空格
selector = njQuery.trim(selector);
// 1.传入 '' null undefined NaN 0 false, 返回空的jQuery对象
if (!selector) {
// return this;
}
// 2. 方法处理
else if (njQuery.isFunction(selector)) {
njQuery.ready(selector);
}
// 2. 字符串
else if (njQuery.isString(selector)) {
// 2.1. 判断是否是代码片段
if (njQuery.isHTML(selector)) {
// 1. 根据代码片段创建所有的元素
var temp = document.createElement("div");
temp.innerHTML = selector;
// // 2. 将创建好定得一级元素添加到jQuery当中
// for (var i = 0; i < temp.children.length; i++) {
// this[i] = temp.children[i];
// }
// // 3. 给jQuery对象添加length属性
// this.length = temp.children.length;
[].push.apply(this, temp.children);
// 4. 返回加工好的this(jQuery)
// return this;
}
// 2.2 判断是否是选择器
else {
// 1. 根据传入的选择器找到对应的元素
var res = document.querySelectorAll(selector);
// // 2. 将找到的元素添加到njQuey上
// for (var i = 0; i < res.length; i++) {
// this[i] = res[i];
// }
// this.length = res.length;
[].push.apply(this, res);
// 3. 返回加工好的this
// return this;
}
}
// 3. 数组
else if (njQuery.isArray(selector)) {
/*
// 3.1 真数组
if ({}.toString.apply(selector) === "[object Array]") {
// 将真数组转成伪数组
[].push.apply(this, selector);
return this;
}
// 3.2 伪数组
else {
// 先将自定义的伪数组转成真数组
var arr = [].slice.apply(selector);
// 在将真数组转成伪数组
[].push.apply(this, arr);
return this;
}
*/
var arr = [].slice.apply(selector);
[].push.apply(this, arr);
// return this;
}
// 4. 除上述类型以外
else {
this[0] = selector;
this.length = 1;
// return this;
}
return this;
},
jquery: "1.1.0",
selector: "",
length: 0,
// [].push找到数组的push方法
// 冒号前面的push将来由njQuery对象调用
// 相当于 [].push.apply(this);
push: [].push,
sort: [].sort,
splice: [].splice,
toArray: function () {
return [].slice.apply(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 === 0) {
return new njQuery();
} else {
return new njQuery(this.get(num));
}
},
first: function () {
return this.eq(0);
},
last: function () {
return this.eq(-1);
},
each: function (fn) {
return njQuery.each(this, fn);
},
};
njQuery.extend = njQuery.prototype.extend = function (obj) {
for (var key in obj) {
this[key] = obj[key];
}
};
njQuery.extend({
// 是不是字符串
isString: function (str) {
return typeof str === "string";
},
// 是不是HTML代码片段
isHTML: function (str) {
return (
str.charAt(0) == "<" &&
str.charAt(str.length - 1) == ">" &&
str.length >= 3
);
},
// 去除字符串两端空格
trim: function (str) {
if (!njQuery.isString(str)) {
return str;
}
// 判断是否支持trim方法
if (str.trim) {
return str.trim();
} else {
return str.replace(/^\s+|\s+$/g, "");
}
},
// 是不是对象
isObject: function (sele) {
return typeof sele === "object";
},
// length属性是否存在
beLength: function (sele) {
return "length" in sele;
},
// 是不是windw对象
isWindow: function (sele) {
return sele === window;
},
// 是不是数组
isArray: function (sele) {
if (
njQuery.isObject(sele) &&
njQuery.beLength(sele) &&
!njQuery.isWindow(sele)
) {
return true;
}
return false;
},
isFunction: function (sele) {
return typeof sele === "function";
},
ready: function (fn) {
// 判断DOM是否加载完毕
if (document.readyState === "complete") {
fn();
} else if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", function () {
fn();
});
} else {
document.attachEvent("onreadystatechange", function () {
if (document.readyState === "complete") {
fn();
}
});
}
},
each: function (obj, fn) {
// 1.判断是否是数组
if (njQuery.isArray(obj)) {
for (var i = 0; i < obj.length; i++) {
var res = fn.call(obj[i], i, obj[i]);
if (res === true) {
continue;
} else if (res === false) {
break;
}
}
}
// 2.判断是否是对象
else if (njQuery.isObject(obj)) {
for (key in obj) {
var res = fn.call(obj[key], key, obj[key]);
if (res === true) {
continue;
} else if (res === false) {
break;
}
}
}
return obj;
},
map: function (obj, fn) {
var res = [];
// 1.判断是否是数组
if (njQuery.isArray(obj)) {
for (var i = 0; i < obj.length; i++) {
var temp = fn(obj[i], i);
if (temp) {
res.push(temp);
}
}
}
// 2.判断是否是对象
else if (njQuery.isObject(obj)) {
for (var key in obj) {
var temp = fn(obj[key], key);
if (temp) {
res.push(temp);
}
}
}
return res;
},
});
njQuery.prototype.init.prototype = njQuery.prototype;
window.njQuery = window.$ = njQuery;
})(window);