// 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_多个引号的用法

    str += "<input id='sel_DayB' width='120' onfocus=\"WdatePicker({skin:'whyGreen',dateFmt ...

  2. jdbcTemplate的Dao层封装

    package com.easyrail.base.dao; import java.io.Serializable; import java.lang.reflect.Field; import j ...

  3. sublime 3 安装go环境

    安装go环境是在go已经安装的情况下, 1 首先安装 Package Control ctrl + · 打开sublime 命令行模式 复制粘贴以下代码 import urllib.request,o ...

  4. Centos 与本地终端 上传、下载 文件

    首先安装lrzsz # yum -y install lrzsz 1.上传文件,执行命令rz,会跳出文件选择窗口,选择好文件,点击确认即可. # rz 运行rz命令后弹出选择文件窗口,找到要上传的文件 ...

  5. 判断 iframe 是否加载完成的完美方法

    一般来说,我们判断 iframe 是否加载完成其实与 判断 JavaScript 文件是否加载完成 采用的方法很类似:var iframe = document.createElement(" ...

  6. chrome 扩展包 postman 的安装

    由于chrome网上应用不能使用.添加扩展程序,需要其他的办法. 1.下载postman安装包.下载地址 2.这一步按照这个下载包中的方法,也可以,可以忽略其错误. 先解压出crx,使用两个办法,使用 ...

  7. string to byte[]

    在平常的开发过程中,经常碰到需要将string转化成byte[]字节数组的情形,有两种方法,在这里总结一下. 使用MemoryStream 代码如下. using (MemoryStream sb = ...

  8. C#中REF和OUT的区别

    在C# 中,既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员更改参数的值,并保持该更改.若要通过引用传递参数, 可使用ref或out关键字.ref和out这两个关键字都能够提供相似的功 ...

  9. 基于KEIL4开发ARM9(S3C2440)的裸机程序

    本文主要介绍如何使用Keil4开发ARM9(S3C2440)裸机程序. 说明: 一.平台: 操作系统:Windows XP系统 KEIL版本:4.73 开发板:ARM9(S3C2440) 二.建立工程 ...

  10. jsp页面往mysql里插入中文后数据库里显示乱码

    1.JSP页面乱码 这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要在页面开始地方用下面代码指定字符集编码即可,<%@ page contentType="text ...