jQuery原生框架-----------------核心框架
// 1、自调防止全局变量污染
(function( window ) {
var version = '1.0.0';
var document = window.document;
var arr = [];
var push = arr.push;
var slice = arr.slice;
var concat = arr.concat;
var obj = {};
var toString = obj.toString;
var hasOwn = obj.hasOwnProperty;
// 3、定义工厂
var jQuery = function( selector ) {
return new jQuery.fn.init( selector );
}
// 4、工厂原型置换&简称
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
jquery: version,
length: 0,
// 把参数包装成一个新的实例返回,这个新的实例记录了调用者(上一级链)
pushStack: function( eles ) {
var $$ = jQuery( eles );
$$.prevObject = this;
return $$;
},
// 返回上一级链,如果没有返回一个新实例
end: function() {
return this.prevObject || jQuery();
},
// 把实例转换为数组返回
toArray: function() {
return slice.call( this );
},
// 按照下标获取原生的元素,支持负数
get: function( index ) {
return arguments.length === 0? this.toArray():
index >= 0? this[ index ]: this[ this.length + index ];
},
// 截取部分元素,返回部分元素构成的新实例
slice: function( start, end ) {
return this.pushStack( slice.call( this, start, end ) );
},
// 按照下标获取jQ包装过的元素,支持负数
eq: function( index ) {
return this.pushStack( this.get( index ) )
},
// 获取jQ包装过的第一个元素
first: function() {
return this.eq( 0 );
},
// 获取jQ包装过的最后一个元素
last: function() {
return this.eq( -1 );
},
push: push,
sort: arr.sort,
splice: arr.splice,
// 传入的fn在DOM构建完毕后执行
ready: function( fn ) {
/*
* 为了防止DOM已经构建完毕后,用户再调用ready方法,
* 造成事件绑定无效,所以先判断DOM有没有构建完毕,
* 如果完毕了,直接执行函数即可。
* */
/*// 如果是现代浏览器,readyState值为interactive或者complete,证明DOM构建完毕,fn直接执行
if ( document.addEventListener &&
( document.readyState === 'interactive' || document.readyState === 'complete' ) ) {
return fn();
}
// IE老版本浏览器,readyState值只有为complete,才能保证DOM构建完毕,fn才能执行
else if (document.readyState === 'complete'){
return fn();
}*/
/*
* 无论是现代浏览器还是IE老版本浏览器,readyState值只要为complete,DOM就一定构建完毕了。
* 另外对于现代浏览器,readyState值如果为interactive,那么代表DOM也构建完毕了。
* */
if( document.readyState === 'complete' ||
( document.addEventListener && document.readyState === 'interactive' ) ) {
fn();
}
else {
/*
* 实现思路:
* 1、判断是否支持addEventListener,支持则绑定DOMContentLoaded事件
* 2、不支持则用attchEvent绑定onreadystatechange事件
* */
if( document.addEventListener ) {
document.addEventListener( 'DOMContentLoaded', fn );
}else {
document.attachEvent( 'onreadystatechange', function() {
if( document.readyState === 'complete' ) {
fn();
}
} );
}
}
// 链式编程
return this;
},
// 遍历实例
each: function( cbk ) {
return jQuery.each( this, cbk );
},
// 遍历实例,返回映射后的新实例
map: function( cbk ) {
return this.pushStack( jQuery.map( this, cbk ) );
}
};
// 7、是工厂自身和原型分别添加一个实现混入继承的方法
jQuery.extend = jQuery.fn.extend = function() {
var arg = arguments, argLen = arg.length;
var key, i = 1;
var target = arg[ 0 ];
if( argLen === 1 ) {
target = this;
i = 0;
}
// 从第二个对象开始遍历
for ( ; i < argLen; i++ ) {
// 把遍历到的每一个对象的所有成员copy给target身上
for ( key in arg[ i ] ) {
if ( arg[ i ].hasOwnProperty( key ) ) {
target[ key ] = arg[ i ][ key ];
}
}
}
return target;
};
// 5、定义构造函数
var init = jQuery.fn.init = function( selector ) {
// 非 undefined、null、NaN、0、''、false
if ( selector ) {
// function
if ( jQuery.isFunction( selector ) ) {
this.ready( selector );
}
// string
else if ( jQuery.isString( selector ) ) {
// html,创建对应的DOM元素,加到实例身上
if ( jQuery.isHTML( selector ) ) {
push.apply( this, jQuery.parseHTML( selector ) );
}
// selector,获取页面中的元素,加到实例身上
else {
push.apply( this, document.querySelectorAll( selector ) );
}
}
// array || likeArray,把数组中所有的数据加到实例身上
else if( jQuery.isLikeArray( selector ) ) {
// 这个不用了,是因为IE8中slice不能操作DOM类型的伪数组
//push.apply( this, slice.call( selector ) );
// 这样做,又用到了apply,一下回到解放军出不来了。
//push.apply( this, concat.apply( [], selector ) );
// 对于IE8来说,当selector为用户自定义的伪数组时,会报错,
// 那么在catch里面把这个伪数组转换为真数组再添加给this就可以了。
try{
push.apply( this, selector );
}catch(e) {
push.apply( this, slice.call( selector ) );
}
}
// 其它,直接把数据加到实例身上
else {
this[ 0 ] = selector;
this.length = 1;
}
}
};
// 6、置换构造原型为工厂原型
init.prototype = jQuery.fn;
// 给jQ添加一堆静态方法
jQuery.extend({
// 把传入的html字符串解析成对应的DOM
parseHTML: function( html ) {
var tempDiv = document.createElement('div');
tempDiv.innerHTML = html;
return tempDiv.childNodes;
},
// 判断数据是不是html字符串
isHTML: function( str ) {
// 如果传入的不是字符串,直接返回false
if ( typeof str !== 'string' ) {
return false;
}
// 如果传入的是字符串,看看这个字符串结构符不符合html字符串结构,符合返回true
if( str[ 0 ] === '<' && str[ str.length - 1 ] === '>' && str.length >= 3 ) {
return true;
}
// 不符合返回false
return false;
},
_isHTML: function( htmlStr ) {
return !!htmlStr && htmlStr[ 0 ] === '<' &&
htmlStr[ htmlStr.length - 1 ] === '>' && htmlStr.length >= 3;
},
// 判断数据是不是对象类型
isObject: function( obj ) {
return (typeof obj === 'object' && obj !== null) || typeof obj === 'function';
},
// 判断数据是不是数组或伪数组
isLikeArray: function( likeArray ) {
// 过滤 function、window、!object
if( jQuery.isFunction( likeArray ) || jQuery.isWindow( likeArray ) || !jQuery.isObject( likeArray ) ) {
return false;
}
// 判断是不是真数组
if( likeArray instanceof Array ) {
return true;
}
// 判断是不是伪数组,要么length值为0,
// 要么length值为number,并且还得有lenght - 1这个属性
if( likeArray.length === 0
|| ( typeof likeArray.length === 'number' && likeArray.length > 0 && (likeArray.length - 1) in likeArray ) ) {
return true;
}
return false;
},
// 判断是不是函数
isWindow: function( win ) {
return !!win && win.window === win;
},
// 判断是不是函数
isFunction: function( fn ) {
return typeof fn === 'function';
},
// 判断是不是字符串
isString: function( str ) {
return typeof str === 'string';
},
// 判断是不是DOM元素
isDOM: function( dom ) {
return !!dom && !!dom.nodeType;
},
// 遍历对象
each: function( obj, cbk ) {
/*
* 实现思路:
* 1、首先却分传入进来的是不是likeArray,
* 2、如果是采用 var i = 0 的遍历方法遍历所有的值,
* 然后把遍历到的下标和值依次传给回调使用,并且设置回调内部的this为遍历到的值
* 3、如果不是likeArray,才有for in的遍历方法遍历所有的值,
* 然后把遍历到的键和值依次传给回调使用,并且设置回调内部的this为遍历到的值
* 4、如果回调的返回结果是false,那么中断遍历
* */
var i, len;
// 如果是数组或者伪数组,才有vai i的方式遍历,效率比较高
if( jQuery.isLikeArray( obj ) ) {
for( i = 0, len = obj.length; i < len; i++ ) {
// 把遍历到的键值传给回调使用,如果回调返回false,
// 那么证明对方不需要再遍历其他数据了,所以break跳出循环。
if( cbk.call( obj[ i ], i, obj[ i ] ) === false ) {
break;
}
}
}
// 否则采用for in的遍历方式
else {
for( i in obj ) {
// 把遍历到的键值传给回调使用,如果回调返回false,
// 那么证明对方不需要再遍历其他数据了,所以break跳出循环。
if( cbk.call( obj[ i ], i, obj[ i ] ) === false ) {
break;
}
}
}
return obj;
},
map: function( obj, cbk ) {
/*
* 实现思路:
* 1、先却分遍历的对象是不是likeArr
* 2、是的话var i方式遍历,把遍历的数据传给回调,
* 同时指定回调内部的this为遍历到的值
* 3、不是for in方式遍历,把遍历的数据传给回调,
* 同时指定回调内部的this为遍历到的值
* 4、收集回调的返回结果,如果不为null或undefined,就存储起来,最终一起返回
* */
var i, len, temp, result = [];
// 如果是数组或者伪数组,才有vai i的方式遍历,效率比较高
if( jQuery.isLikeArray( obj ) ) {
for( i = 0, len = obj.length; i < len; i++ ) {
// 把遍历到的键值传给回调使用,
// 同时接收回调的返回值,
// 如果值不为null或undefined,那么存储到result数组
temp = cbk.call( obj[ i ], i, obj[ i ] );
if( temp != null ) {
result.push( temp );
}
}
}
// 否则采用for in的遍历方式
else {
for( i in obj ) {
// 把遍历到的键值传给回调使用,
// 同时接收回调的返回值,
// 如果值不为null或undefined,那么存储到result数组
temp = cbk.call( obj[ i ], i, obj[ i ] );
if( temp != null ) {
result.push( temp );
}
}
}
return result;
}
});
// 2、暴露工厂&提供一个工厂简称
window.jQuery = window.$ = jQuery;
})( window );
jQuery原生框架-----------------核心框架的更多相关文章
- jquery widget开发——核心框架
框架代码: $.widget("myns.myplugin", { //默认参数 options: { }, //初始化,控件生命周期内只运行一次 _init: function ...
- 10天学会phpWeChat——第一天:核心框架的目录结构
phpWeCaht是一款优秀的PC网站+微信公共号开发框架. 本博客系列将图文结合,详细介绍phpWeChat 的使用方法,今天进入phpWeChat系列教程之<10天学会phpWeChat&g ...
- 程序员的自我救赎---1.4.1:核心框架讲解(DAL)
<前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八) ...
- Jquery学习---Easy UI 框架
Jquery的easyui 1.1. easyui的目录分析 以 jquery Easy UI 1.3.2 版本学习 demo 实例 locale 国际化信息 plugins 框架一些插件 src 源 ...
- Vue框架核心之数据劫持
本文来自网易云社区. 前瞻 当前前端界空前繁荣,各种框架横空出世,包括各类mvvm框架横行霸道,比如Angular.Regular.Vue.React等等,它们最大的优点就是可以实现数据绑定,再也不需 ...
- 小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)?
小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)? 自 2017-1-9微信小程序诞生以来,历经2年多的迭代升级,已有数百万小程序上线,成为继Web.iOS.Androi ...
- jQuery Mobile与QUI框架的异曲同工之处
最近一直在研究jQuery Mobile框架,这是jQuery的官方移动版UI框架,专门用来开发手机与平板电脑方面的应用.结果越来越觉得它和我的QUI框架的开发思路非常相似,很多地方都有异曲同工之妙. ...
- python运维开发(十七)----jQuery续(示例)web框架django
内容目录: jQuery示例 前端插件 web框架 Django框架 jQuery示例 dom事件绑定,dom绑定在form表单提交按钮地方都会绑定一个onclick事件,所有查看网站的人都能看到代码 ...
- C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 ...
随机推荐
- Spring-cloud & Netflix 源码解析:Eureka 服务注册发现接口 ****
http://www.idouba.net/spring-cloud-source-eureka-client-api/?utm_source=tuicool&utm_medium=refer ...
- property内存管理策略
1普通数据,用weak 2delegate,用weak 3一般对象,用strong 4NSString,用copy 5block,用copy
- 了解真实的『REM』手机屏幕适配
rem 作为一个低调的长度单位,由于手机端网页的兴起,在屏幕适配中得到重用.使用 rem 前端开发者可以很方便的在各种屏幕尺寸下,通过等比缩放的方式达到设计图要求的效果. rem 的官方定义『The ...
- 微信webview
会露出灰色的地步 https://segmentfault.com/q/1010000004295291 有说用iscroll5来解决,但是明显有bug啊 https://segmentfault.c ...
- Git代码管理常用命令
1) 远程仓库相关命令 检出仓库:$ git clone git://github.com/jquery/jquery.git查看远程仓库:$ git remote -v添加远程仓库:$ git re ...
- 修改XML指定标签的内容
修改Xml指定标签内容(我这是去掉指定标签内容的空格) 其实就是个很简单的方法,需要的盆友直接拿走. test.xml <?xml version="1.0" encodin ...
- [ios学习笔记之视图、绘制和手势识别]
一 视图 二 绘制 三 手势 00:31 UIGestureRecognizer 抽象类 两步 1添加识别器(控制器或者视图来完成) 2手势识别后要做的事情 UIPanGestureRecognize ...
- 常用的WEB服务
1.股票行情数据 Web Service(支持香港.深圳.上海基金.债券和股票:支持多股票同时查询) http://www.webxml.com.cn/WebServices/StockInfoWS ...
- 并发编程 20—— AbstractQueuedSynchronizer 深入分析
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- smartform
SMARTFORMS中一般对于固定样式,格式的某一块会选择使用TEMPLATE或者TABLE. 表:上下高度不限,以窗口高度为限.循环输出表数据,每次循环都会按照表行输出,表头和表尾可控制输出.表行中 ...