在网上下了一个类似于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);

  

分析一个类似于jquery的小框架的更多相关文章

  1. 分析一个类似于jquery的小框架 (2)

    核心构造函数 (function ( window, undefined ) { // 定义Itcast构造函数 function Itcast ( selector ) { return new I ...

  2. 【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建

    /* * @Author: 我爱科技论坛 * @Time: 20180715 * @Desc: 实现一个类似于JQuery功能的框架 * V 1.0: 实现了基础框架.事件框架.CSS框架.属性框架. ...

  3. 【JavaScript框架封装】实现一个类似于JQuery的DOM框架的封装

    // DOM框架(选择器框架) (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 向现 ...

  4. 【JavaScript框架封装】实现一个类似于JQuery的缓存框架的封装

    // 缓存框架 (function (xframe) { /** * 实现了缓存框架的临时存储功能(内存存储) * @type {{data: Array, get: (function(*): *) ...

  5. 【JavaScript框架封装】实现一个类似于JQuery的动画框架的封装

    // 动画框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({}); // 不需要参与链式访问的 ...

  6. 【JavaScript框架封装】实现一个类似于JQuery的属性框架的封装

    // 属性框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 获取/设置某一个元素 ...

  7. 【JavaScript框架封装】实现一个类似于JQuery的选择框架的封装

    // 选择框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({}); // 不需要参与链式访问的 ...

  8. 【JavaScript框架封装】实现一个类似于JQuery的事件框架的封装

    // 事件框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 实现一个浏览器的基本 ...

  9. 【JavaScript框架封装】实现一个类似于JQuery的内容框架的封装

    // 内容框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * .html()用为读 ...

随机推荐

  1. Ubuntu 16.04 安装ftp服务器传输文件

    最近在搞深度学习,老师比较宝贝他的服务器,要求我以后负责管理服务器.往后所有要使用服务器的人都必须向我申请账号,然后只允许客户端访问,使用文件传输软件传输文件.像我这样一个linux菜逼,这种要求不是 ...

  2. [转]''\\=DevExpress 中 汉化包 汉化方法

    [DevExpress]DevExpress 中 汉化包 汉化方法 2016-02-17 21:13 1781人阅读 评论(0) 收藏 举报  分类: DevExpress(24)  版权声明:本文为 ...

  3. Buffalo最佳实践

    本文将介绍Buffalo AJAX的两种配置的最佳实践,这个AJAX框架还是中国大师开发的,用起来估计是最方便.最简单的一个 准备工作:官网下载buffalo-2.0-bin,也可以下载buffalo ...

  4. nginx下rewrite参数超过9个的解决方法

    nginx 在处理多于9个参数的时候,是采用重命名的方法来实现的: /?m?([0-9,]*)h?(\d*)a?([0-9,]*)c?(\d*)s?(x?f?(?P<f>[0-9,]*)/ ...

  5. Eclipse插件安装方式及使用说明

    拷贝安装方式 1.通过ECLIPSE_HOME\plugins安装 在eclipse的主目录ECLIPSE_HOME, 比如在我的机器上安装的目录是:ECLIPSE_HOME有一个plugins的目录 ...

  6. Thread.join简单介绍

    百度了一下,终于明白了.这个解释最简单: 前提:join()方法肯定是被某个线程调用的.   A线程正在执行,突然执行的时候碰到了B.join(), 那么,A线程就必须要等到B线程执行完之后才能执行. ...

  7. HDU 1698 Just a Hook(线段树 区间替换)

    Just a Hook [题目链接]Just a Hook [题目类型]线段树 区间替换 &题解: 线段树 区间替换 和区间求和 模板题 只不过不需要查询 题里只问了全部区间的和,所以seg[ ...

  8. 慕课编程题JS选项卡切换

    Javascript进阶篇的最后一节是一个选项卡切换的编程,要求效果如下. 这里涉及到两块,一个是内容的切换显示,一个是红色的边框样式切换. 内容切换可以用纯js代码实现,但当这里还需设置一个红色边框 ...

  9. Android高手速成

    第一部分 个性化控件(View)    http://www.cnblogs.com/huwei0814/p/3796659.html 第二部分 工具库    http://www.cnblogs.c ...

  10. selenium之操作ChromeDriver

    链接:http://www.testwo.com/blog/6931 1.下载ChromeDriver驱动包(下载地址: http://chromedriver.storage.googleapis. ...