1. 首先我们在看jQ代码的时候 发现整体是一个 闭包函数
// JQ的整体是一个自调用函数/闭包
(function(window,undefined){
})(window)
作用:
1.防止全局变量污染(只提送2个变量 $ 和 jQuery)
2.保护内部的代码不会被覆盖
其中 里面的2个参数window
和undefined
值默认不能被修改,但是在IE9-是可以被修改的
window
不用多解释,全局的对对象
2.JQ使用的事工厂函数
//自调用函数
(function(window,undefiend){
//1.创建工厂函数
var jQuery = function(select){
//返回一个 构造函数
return new jQuery.fn.init(select);
}
//2. 设置元素对象和原型对象
jQuery.fn = jQuery.prototype = {
constructor:jQuery,
//初始化方法 匿名的构造函数
init:function(select){
}
}
//3.更改init构造函数的原型对象 指向 jQuery.prototype
jQuery.fn.init.prototype = jQuery.prototype;
//4.给外界提供一个变量
window.jQuery = window.$ = jQuery;
})(window);
3.jQ的参数分析
1.如果条件判断为假 0 false null undefined NaN ... 返回空的jQ实例对象
jQuery.fn = jQuery.prototype = {
constructor:jQuery,
init:function (selector) {
//条件判断为假 返回空的jQ对象
if(!selector)
{
return this;
}
}
}
- 字符串(
标签
) 返回所有标签保存到jQ实例对象 比如$("我是spanA我是spanB")
jQuery.fn = jQuery.prototype = {
constructor:jQuery,
init:function (selector) {
//[1] 条件判断为假 返回空的jQ对象
if(!selector)
{
return this;
}
//[2] 参数是字符串
else if(Tool.isString(selector))
{
//参数是标签
//
//总结判断的条件:必须以<开头 && 必须以>结尾 && 长度>=3
//charAt(index) 获取字符串中指定的字符 "zhangsan"
//容错性处理:包容用户
selector = Tool.trim(selector);
if(Tool.isHTML(selector))
{
//console.log("参数是标签");
//console.log(typeof selector);
//把参数中所有的一级标签都保存到jQ实例对象中返回
//分析: 创建一个临时的div 存储标签字符串
// 把所有获取的标签都存到当前jQ实例对象中(this)
// 更新length的值
var tempEle = document.createElement("div");
tempEle.innerHTML = selector;
var nodes = tempEle.children;
//console.log(tempEle);
//console.log(nodes);
for(var i = 0;i" && html.length >=3
},
trim:function (text) {
//检测当前环境是否支持trim方法,如果支持那么就直接使用
if(text.trim)
{
return text.trim();
}else
{
return text.replace(/^\s+|\s+$/g,"")
}
}
}
- 字符串(
选择器
)把参数中所有的一级标签都保存到jQ实例对象中返回
比如:
//获取参数
var nodes = document.querySelectorAll(selector);
//遍历 查看是否有自标签
for(var i = 0;i
4.数组 |
伪数组(本质是对象)
返回jQ实例对象
[].push.apply(this,selector);
return this; //返回jQ对象
5.如果参数是函数,那么会监听DOM的加载,等DOM加载完执行回调函数中的代码
//闭包函数
(function(window,undefined){
//1.创建工厂函数
var jQuery = function(select){
return new jQuery.fn.init(select);
};
//2.设置原型对象
jQuery.fn = jQuery.prototype = {
constructor:jQuery,
init:function(select){
//1.判断条件是否为假
if(!select){
return this;
} else if(tool.isFunction(select)){
this.ready(selector);
}
//2.判断字符串
//console.log(typeof selector);
//把参数中所有的一级标签都保存到jQ实例对象中返回
//分析:(001)需要根据字符串获取一级标签
// (002)把所有获取的标签都存到当前jQ实例对象中(this)
// (003)更新length的值
else if(tool.isString(select)){
//取出空格
select = tool.trim(select);
//匹配标签字符串
if(tool.isHTML(select)){
//创建一个临时div 包裹
var tempElement = document.createElement("div");
//把标签字符串设置 div的内容 获取div的 子元素
tempElement.innerHTML = select;
var nodes = tempElement.children;
for(var i =0 ; i < nodes.length; i ++){
//包装成 JQ对象 this就是创建JQ的对象
this[i] = nodes[i];
}
this.length = nodes.length;
return this;
}
//字符串是选择器
else{
//(001) 根据参数获取所有指定的标签
//(002) 把所有获取的标签存储到jQ实例对象中返回
//(003) 更新length的值,返回jQ实例对象
//"div"
//#demoID
//.box
// var nodes = document.querySelectorAll(select);
// for(var i = 0; i < nodes.length; i ++){
// this[i] = nodes[i];
// }
// this.length = nodes.length;
// apply借调函数的使用
// this借调数组[] push的方法
// push是 Array.prototype.push 的原型方法
//这个方法 等价于 上面的for 遍历
[].push.apply(this,document.querySelectorAll(select));
return this;
}
}
//3.判断是否为 数组/为数组
else if(tool.isArray(select) || tool.isLikeArray(select)){
//IE8之前调用下面的方法会报错
//select是伪数组的时候
//处理,把为数组转化为数组
var arrt = [].slice.call(select);
[].push.apply(this,arrt);
return this;
}
//其他参数
else{
this[0] = select;
this.length = 1;
}
},
ready:function(fn){
//判断是不是已经加载完成了,如果是 直接调用
if(document.readyState == "complete") {
fn();
return;
}
//不是
//监听DOM 加载完成
if(document.addEventListener){
document.addEventListener("DOMContentLoaded",fn);
} else{
//兼容IE的方法
document.attachEvent("onreadystatechange",function(){
if(document.readyState == "complete") {
fn();
}
});
}
}
}
//抽出的工具方法
var tool = {
isObject:function(obj){
return typeof obj == "object" && obj != null;
},
isWindow(obj){
return obj === window.window;
},
isString:function(str){
return (typeof str === "string");
},
isHTML:function(html){
//判断是字符串是否是标签 zheshi
return html.chatAt(0) === "<" && html.chatAt(html.lenth -1) === ">"&&html.length >= 3;
},
trim:function(text){
//判断是否支持这个方法
if(text.trim){
return text.trim();
} else{
//处理字符串中的空格
// 把空格替换掉
return text.replace(/^\s+|\s+$/g,"");
}
},
isArray:function(arr){
//处理是不是数组
if(Array.isArray){
//ES5
return Array.isArray(arr);
} else{
//ES5之前的
return Object.prototype.toString.call(arr) === "[object Array]";
}
},
/**
* (1) 是对象
* (2) 拥有length属性
* (3) 拥有length-1属性
* (4) 不是window
*/
isLikeArray:function(likeArray){
return this.isObject && length in likeArray && likeArray.length - 1 in likeArray && !tool.isWindow(likeArray);
},
isFunction:function(fn){
return typeof fn == "function";
}
};
//3.更改init的构造函数的原型对象的指向
jQuery.fn.init.prototype = jQuery.prototype;
jQuery.tool = tool;
//4.提供全局变量给外部
window.jQuery = window.$ = jQuery;
})(window);
4.工具优化---插件机制
我们知道jQ
提供的2个参数分别是$
和jQuery
,那么如何暴露给外面一些工具方法,或者是对象方法呢?
答案是:原型对象
//优化工具方法
jQuery.fn.extend = jQuery.extend = function(obj){
for(var i in obj){
this[i] = obj[i];
}
}
jQuery.fn.extend
其实就是jQuery.prototype..extend
给原型对象扩展方法
jQuery.extend
扩展其实就是jQuery = function(){}
函数,扩展静态的属性或者方法
比如:
// 工厂函数 添加属性或者方法
jQuery.extend({
isObject:function(obj){
return typeof obj == "object" && obj != null;
},
isWindow:function(obj){
return obj === window.window;
},
isString:function(str){
return (typeof str == "string");
},
isHtml:function(html){
return html.charAt(0) === "<" && html.charAt(html.length -1) === ">" && html.length >= 3;
},
trim:function(text){
if(text.trim){
return text.trim();
}else {
//排除空格
return text.replace(/^\s+|^s+$/g,"");
}
},
isArray:function(tempArr){
if(Array.isArray){
return Array.isArray(tempArr);
}else{
//es5之前 调用object的原型对象tostring 处理
return Object.prototype.toString.call(tempArr) == "[object Array]";
}
},
isLikeArray:function(tempArr){
return this.isObject && length in tempArr && tempArr.length - 1 in tempArr && !this.isWindow(tempArr);
},
isFunction:function(fn){
return typeof fn == "function";
}
});