// 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原生框架-----------------核心框架的更多相关文章

  1. jquery widget开发——核心框架

    框架代码: $.widget("myns.myplugin", { //默认参数 options: { }, //初始化,控件生命周期内只运行一次 _init: function ...

  2. 10天学会phpWeChat——第一天:核心框架的目录结构

    phpWeCaht是一款优秀的PC网站+微信公共号开发框架. 本博客系列将图文结合,详细介绍phpWeChat 的使用方法,今天进入phpWeChat系列教程之<10天学会phpWeChat&g ...

  3. 程序员的自我救赎---1.4.1:核心框架讲解(DAL)

    <前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八) ...

  4. Jquery学习---Easy UI 框架

    Jquery的easyui 1.1. easyui的目录分析 以 jquery Easy UI 1.3.2 版本学习 demo 实例 locale 国际化信息 plugins 框架一些插件 src 源 ...

  5. Vue框架核心之数据劫持

    本文来自网易云社区. 前瞻 当前前端界空前繁荣,各种框架横空出世,包括各类mvvm框架横行霸道,比如Angular.Regular.Vue.React等等,它们最大的优点就是可以实现数据绑定,再也不需 ...

  6. 小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)?

    小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)? 自 2017-1-9微信小程序诞生以来,历经2年多的迭代升级,已有数百万小程序上线,成为继Web.iOS.Androi ...

  7. jQuery Mobile与QUI框架的异曲同工之处

    最近一直在研究jQuery Mobile框架,这是jQuery的官方移动版UI框架,专门用来开发手机与平板电脑方面的应用.结果越来越觉得它和我的QUI框架的开发思路非常相似,很多地方都有异曲同工之妙. ...

  8. python运维开发(十七)----jQuery续(示例)web框架django

    内容目录: jQuery示例 前端插件 web框架 Django框架 jQuery示例 dom事件绑定,dom绑定在form表单提交按钮地方都会绑定一个onclick事件,所有查看网站的人都能看到代码 ...

  9. C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)

    译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 ...

随机推荐

  1. iOS开发 iOS9横屏后状态栏隐藏处理

    - (BOOL)prefersStatusBarHidden { return NO; }

  2. Session的使用过程中应注意的一个小问题

    在学习AllEmpty大神的从零开始编写自己的C#框架系列文章中,发现的问题:在验证码的缓存Session["vcode"]的赋值时,发现Session["vcode&q ...

  3. contiki-rime-单跳单播

    rucb是单跳单播的最顶层,将数据以块为单位进行传输(Bulk transfer). ruc,Reliable communication,保证可靠通信,主要实现确认和序列功能. suc,Stubbo ...

  4. linux指令(一)文件的操作

    ls -i 查看文件的inode号 find ./ inum 1651190 -exec rm  -i {} \; 根据inode号删除文件

  5. mac下使用sencha cmd+extjs6

    笔者刚接手公司一个项目,后台是使用extjs6做前端,php做api接口,两者通过ajax交互 没办法,不管接手的项目多么的挫逼,都还是要上的,拿人钱财替人消灾嘛 首先是安装sencha cmd ,百 ...

  6. NotORM(PHP的ORM框架)

    类似Thinkphp映射到表的ORM机制. 网址:http://www.notorm.com/ <?php //require_once ‘init.php’;require_once ‘Not ...

  7. 【xsy1629】可持久化序列 - 可持久化平衡树

    题意 你现在要用数据结构维护一个长度为n的序列. 这个序列支持三种操作: 1 l r:将序列中的第l项到第r项这一段翻转. 2 l r:查询序列中[l,r]这一段的和. 3 p:回到第p个历史版本. ...

  8. SPSS数据分析—典型相关分析

    我们已经知道,两个随机变量间的相关关系可以用简单相关系数表示,一个随机变量和多个随机变量的相关关系可以用复相关系数表示,而如果需要研究多个随机变量和多个随机变量间的相关关系,则需要使用典型相关分析. ...

  9. SQLite3中自增主键归零方法

    当SQLite数据库中包含自增列时,会自动建立一个名为 sqlite_sequence 的表.这个表包含两个列:name和seq.name记录自增列所在的表,seq记录当前序号(下一条记录的编号就是当 ...

  10. Wind7外接显示器选择拓展模式后,鼠标只能往右移动才能切换到外接显示器上,不能修改切换方向

    win7外接显示器选择拓展模式后,为什么鼠标只能往右移动才能切换到外接显示器上,不能修改切换方向 打开控制面板-->显示 其他不变的情况下,鼠标拖动上面的两个显示器图标,拉出你希望的方向即可.