// 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. js平滑滚动到顶部,底部,指定地方

    [原文链接] 采用锚点进行页面中的跳转的确很方便,但是要想增加网页的效果,可以使用jquery中的animate,实现滚动的一个动作,慢慢的滚动到你想跳转到的位置,从而看起来会非常高大上. [示例演示 ...

  2. adb shell使用

    adb shell可以用来操纵数据库 1.在cmd界面 输入adb shell 进入adb shell 2.使用cd 切换到工作目录:使用ls查看文件 3.使用sqlite3+数据库名字 打开某个数据 ...

  3. 在linux上部署web环境

    1.升级python到2.7版本(通过源码包重新安装一个2.7版本的python):wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9. ...

  4. [HTML/HTML5]6 使用图像

    6.1  将图像作为Web页面的前景元素 使用img元素,就可以在Web页面中添加图像.img是image的缩写.只需在img元素中添加src(source的缩写)属性,并为该属性设置相应的值,就可以 ...

  5. nodejs学习篇

    最近在找工作,然后都说会个后台语言更好,选来选去,觉得nodejs比较有意思,就开始着手学这个了. 其实个人觉得,没有人领一下或者没有本好书去跟着做,这样的学习实在特别累,像我这种刚入门的菜鸟,完全搞 ...

  6. xcode报错http

    问题: Xcode项目发送网络请求时,报错:“App Transport Security has blocked a cleartext HTTP (http://) resource load s ...

  7. mongodb的一些小总结

    mongodb的安装,官网下载想要的版本,可视化工具mongovue(注意不支持mongodb3.0以上的版本) 下载mis安装,解压后bin,... 1.配置环境变量,将H:\mongodb\mon ...

  8. 为OpenEdx中lms注册模块扩展字段

    最近遇到需求,需要扩展注册的字段,例如新增手机mobile字段 1.打开register.html文件   路径为\edxapp\edx-platform\lms\templates\register ...

  9. AngularJS学习笔记

    一.初识AngularJS:1.Angularjs通过创建实时模板来代替视图,而不是将数据合并进模板后更新DOM,任何一个独立视图组件中的值都是动态替换的. 二.数据绑定和第一个AngularJS W ...

  10. jsessionid 导致重定向404的问题

    http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletResponse.html#encod ...