分析一个类似于jquery的小框架

时间:2023-12-15 09:10:20

在网上下了一个类似于jQuery的小框架,分析源码,看看怎么写框架。

选择器Select

//用沙箱闭包其整个代码,只有itcast和I暴漏在全局作用域
(function( window , undefined){
//Itcast函数,参数:selector。返回值一个Itcast对象,功能:new Itcast。prototype。init()
function Itcast(selector){
return new Itcast.prototype.init();
}
// Itcast的原型属性用替换重新定义
Itcast.prototype = {
constructor: Itcast,
type: "Itcast",
length: 0,
//constructor指向构造函数Itcast,type记录对象类型“Itcast”,length:变成伪数组
// init函数 功能:Itcast对象的真正的构造函数,根据参数类型,进行不同的处理: 参数:selector。
// 返回值:只要在适当的位置返回即可,构造函数不需要返回值,但是为了提醒这里是为了创建对象,所以写成return this
//因为init是构造函数,this就是指创建出来的这个对象,现在要把获取到的dom对象全部追加到this中来,再通过Itcast返回
// 。因为Itcast和init是用的同一个原型,所以认为此处创建出来的就是Itcast对象
init:function(selector){
var push = [].push;
if( typeof selector == "string"){
// 如果selector是html字符串,用parseHtml将其转成DOM伪数组,再转成this(Itcast伪数组)
if( selector.charAt(0) == "<"){
push.apply(this , parseHTML(selector));
}else{
// 如果selector是选择器。用Select函数,
push.apply(this , Select(selector));
} }
// 如果是function ,近似于onload
if( typeof selector == "function"){ }
// 如果是dom,追加到this(Itcast伪数组)中
if( selector.nodeType ){ }
// 如果是Itcast对象,追加到新的Itcast对象中返回
if( selector.type = "Itcast" ){ }
}
} //让init的原型属性指向Itcast。prototype。即有init创建出来的对象也就是Itcast对象了
Itcast.prototype.init.prototype = Itcast.fn = Itcast.prototype;
//设定Itcast的扩展方式,Itcast。extend(静态成员扩展) 。 Itcast.prototype.extend(动态成员扩展)
// .函数参数: 对象option。 返回值: 无, 功能:将option中的属性或方法依次添加给Itcast或Itcast.fn
Itcast.fn.extend = Itcast.extend = function(option){
for( var k in option){
this[ k ] = option[ k ];
}
}
//模块化,功能化。(构造函数的补充)
//扩充静态成员
//选择器Select(闭包,仅将Select暴漏在外面)参数:无,返回值Select函数。
// 功能:再沙箱中将Select函数定义好,
var Select = (function(){
//数据初始化:
//将某些浏览器是否支持a方法用对象support储存起来以免每一次动用函数的时候都要进行查找
// 是否提供可以看函数体是否包含 [native code]即可;,正则表达式的变量以r开头
var rnative = /\[native code\]/,
push = [].push ,
i,
div = document.createElement("div");
var support = {
qsa: rnative.test(document.querySelectorAll),
getByClass : rnative.test( document.getElementsByClassName),
getByClass2: rnative.test(div.getElementsByClassName),
trim: rnative.test(String.prototype.trim),
indexOf: rnative.test(Array.prototype.indexOf),
}
// 要用的函数提前准备好
// push,push没有兼容性问题但是push.apply再IE低版本,不能展开伪数组,会报错
// ,因此用try{}catch的方法兼容
try{
push.apply([],document.getElementsByTagName("*"));
}catch(e){
//z自定义push.apply的函数,参数数组a,伪数组b, 返回值 数组a,
// 功能:将b中的内容添加到 a当中;
var push = {
apply : function( a , b){
for( var i =0 ; i< b.length ; i++ ){
a[ a.length++ ] = b[ i ];
}
return a;
}
}
}
//trim 参数:字符串 ,返回值:首位去除空白的I字符串。功能:将字符串的两端的空白去出,并返回
function trim( str ){
if( support.trim ){
return str.trim();
}else{
var rtrim = /^\s+|\s+$/;
return str.replace( rtrim , "");
}
}
// indexOf,参数数组arr,a要查找项,返回值:a的索引值,如果没有返回-1
//indexOf 还需要一个参数, 就是 查找的开始位置
function indexOf( arr , a,startIndex){
startIndex = startIndex || 0;
if(support.indexOf){
return arr.indexOf(a , startIndex);
}
for(var i = startIndex; i< arr.length ;i++){
if( arr[ i ] === a){
return i;
}
}
return -1;
}
//unique函数,参数:数组 ,返回值:去重之后的数组,功能: 将穿进来的数组中的重复项去除
function unique( arr ){
var array = [];
for( var i=0 ; i< arr.length ;i++){
if(indexOf( array ,arr[ i ]) == -1){
array.push( arr[i]);
}
}
return array;
}
//核心函数Select:参数:selector选择器, 要被添加元素的数组或伪数组results, 返回值results
//功能: 将selector对应的DOM对象,追加到results中输出
function Select(selector ,results){
results = results || [];
if( typeof selector !== "string"){
return ;
}
//如果浏览器支持querySelectorAll就用,如果不支持,就自己定义一个select2
if( support.qsa ){
return document.querySelectorAll( selector );
}else {
return select2( selector);
}
}
// select2,参数:selector选择器,返回值dom对象,
function select2( selector ,results){
// 功能:看选择器是不是并集选择器,将selector用trim函数去掉首尾的空白()
results = results || [];
// ,再用split函数切割成数组,
var arr = selector.split(",");
for( i = 0 ; i < arr.length ; i++){
// 再用select3函数进行处理,将切割好的字符串用trim方法取出前后空白
select3( trim(arr[ i ]) , results);
}
return unique(results);
}
function select3 ( selector , results){
results = results || [];
//select3函数:参数select ,返回值dom对象。功能:判断选择器是“*”还是id,还是类,还是标签
var first = selector.charAt(0);
//注意如果是类选择器,document.getElementsByClassName有浏览器兼容性问题。
//区分好后,调用相应的函数进行处理
//此处屏蔽掉后代选择器的影响,此时如果selector经过了首尾去空格后还有空格,说明是后代选择器
if( selector.slice(" ").length == 1){
if(selector == "*"){
/*
results = document.getElementsByTagName("*");
return results;
,如果results原来就有内容,此处把results中的内容全部覆盖了所以不行,
要将选择器对应的dom元素挨个追加到results中
*/
}else if( first == "#"){
return id(selector.slice(1) , results);
}else if( first == "."){
//类
return c(selector.slice(1),results);
}else {
//标签
return t(selector , results)
}
}else{
//如果是后代选择器,此处咱不处理,抛出一个bug,提示升级浏览器
throw new Error("您的浏览器版本过低,请升级浏览器")
}
} //参数:选择器selector 被追加元素的数组。 返回值: results
//功能: 将selector对应的元素挨个追加到results中并输出,
function id( selector ,results ){
results = results || [];
push.apply(results , document.getElementById(selector));
return results;
}
// 标签
function t( selector , results){
results = results || [];
push.apply( results , document.getElementsByTagName( selector));
return results;
}
//类,getElementsByClassName有浏览器兼容行问题,
function c( selector , results ){
results = results || [];
push.apply( results , getByClass( selector , document));
return results;
} //兼容类选择器,参数:类名className ,查找返回node,返回值:返回查找到的dom元素数组
//功能: 用className属性查找node中的符合条件的dom对象,并返回对象数组
function getByClass(className , node){
node = node || document;
//如果浏览器支持
if( node == document && support.getByClass || node.nodeType && support.getByClass2){
return node.getElementsByClassName(className);
}else{
//如果浏览器不支持
//获取所有的标签,遍历
var list = node.getElementsByTagName("*"),
arr = [],
tempClassName;
for( var i = 0 ; i< list.length ;i++){
tempClassName = list[ i ];
if( !tempClassName ){
continue;
} //再class属性存在的情况下
//用slice(“ ”)分割
//判断是否与className相同
//如果相同追加到results中
if(indexOf(tempClassName.slice(" "),className) !== -1){
arr.push(tempClassName);
}
}
return arr; } } return Select;
})(); // 解析html字符串parseHTML
//在解析过程中,需要在内存中创建一个node,为了不暴漏在外面使用沙箱(自调自用的函数,返回该数组)
//参数:selector,(html字符串),返回值存储dom的数组,功能: 将html字符串转化成dom对象储存在数组中
Itcast.parseHTML =(function (){
var node = document.createElement("div");
var arr = [];
function parseHTML(selector){
node.innerHTML = selector;
arr.push.apply(arr , node.childNodes);
return arr;
}
return parseHTML;
})(); //扩充实例成员
Itcast.fn.extend({
appendTo: function ( parent , child ){
parent.appendChild( child );
}
}) //将Itcast挂在window上
window.Itcast = window.I = Itcast;
})(window);