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);