分析一个类似于jquery的小框架
在网上下了一个类似于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的小框架的更多相关文章
- 分析一个类似于jquery的小框架 (2)
核心构造函数 (function ( window, undefined ) { // 定义Itcast构造函数 function Itcast ( selector ) { return new I ...
- 【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建
/* * @Author: 我爱科技论坛 * @Time: 20180715 * @Desc: 实现一个类似于JQuery功能的框架 * V 1.0: 实现了基础框架.事件框架.CSS框架.属性框架. ...
- 【JavaScript框架封装】实现一个类似于JQuery的DOM框架的封装
// DOM框架(选择器框架) (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 向现 ...
- 【JavaScript框架封装】实现一个类似于JQuery的缓存框架的封装
// 缓存框架 (function (xframe) { /** * 实现了缓存框架的临时存储功能(内存存储) * @type {{data: Array, get: (function(*): *) ...
- 【JavaScript框架封装】实现一个类似于JQuery的动画框架的封装
// 动画框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({}); // 不需要参与链式访问的 ...
- 【JavaScript框架封装】实现一个类似于JQuery的属性框架的封装
// 属性框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 获取/设置某一个元素 ...
- 【JavaScript框架封装】实现一个类似于JQuery的选择框架的封装
// 选择框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({}); // 不需要参与链式访问的 ...
- 【JavaScript框架封装】实现一个类似于JQuery的事件框架的封装
// 事件框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 实现一个浏览器的基本 ...
- 【JavaScript框架封装】实现一个类似于JQuery的内容框架的封装
// 内容框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * .html()用为读 ...
随机推荐
- ArcGis 字段计算表达式写法注意事项
在ArcGis中,经常用到字段的计算.对于复杂的字段计算,需要写代码来实现,在使用ESRI.ArcGIS.DataManagementTools.CalculateField 类时,Python代码中 ...
- 多线程下的 Lambda表达式 异步 WebClient 读取程序图标,来作为托盘 图标 logo ico
//读取程序图标,来作为托盘图标this.notifyIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(System.Windows.Form ...
- 单例实现c++
#include <iostream> using namespace std; class Singleton { public: static Singleton *GetInstan ...
- Hibernate5.2之多对多关联关系(六)
Hibernate5.2之多对多关联关系(六) 一.简介 Hibernate中多对多关联关系在工程中使用的频率也是非常高的,例如:大学中学生选课.用户订单等.在本博客中笔者一样通过实例代码为读者阐述H ...
- 数据挖掘之KNN算法(C#实现)
在十大经典数据挖掘算法中,KNN算法算得上是最为简单的一种.该算法是一种惰性学习法(lazy learner),与决策树.朴素贝叶斯这些急切学习法(eager learner)有所区别.惰性学习法仅仅 ...
- Oracle补习班第五天
Great minds have purpose,others have wishes. 杰出的人有着目标,其他人只有愿望 控制文件是小型二进制文件,只能在mount阶段新建 1,重做控制文件 alt ...
- 关于print和echo的区别
我的想法是print是函数,echo是语句.有一个点很难去说明就是为什么可以执行print 666.可以这样不加括号,象print(666);至于为什么一定要认为print是函数,而非网上说的语句和函 ...
- 如何消除移动端a标签点击时的蓝色底色以及a标签link、visited、hover、active的顺序
1.消除a标签移动端点击时的蓝色底色 -webkit-tap-highlight-color:transparent 2.link.visited.hover.active的顺序 a:link{tex ...
- centOS安装网卡驱动
作为一个小白来说,安装驱动之类的真是无心下手的感觉,在学习了http://www.centoscn.com/image-text/config/2013/0816/1269.html这篇帖子的步骤之后 ...
- 查看MS SQL SERVER 错误日志
查看目的: 错误日志的查看是确保过程已成功完成(例如,备份和恢复操作,批处理命令,或其他脚本和过程).这可以帮助检测任何当前或潜在的问题,包括自动恢复信息(尤其是如果SQL Server实例已停止并重 ...