jQuery的一些简单知识点(二)
2017-09-21 09:32
302 查看
1.把入口函数和框架融合,extend混入扩展静态方法,IE8中apply的兼容性问题
2.jQuery中静态方法Each(),数组的forEach(),以及自定义的each()的使用,以及each()中的this指向问题
3.遍历中断,这里最好打个断点看下函数的执行流程,加强对回调函数的理解。
4.模仿jQuery中map()的实现
<body> <script> (function( w ) { // 工厂 function jQuery( selector ) { return new jQuery.fn.init( selector ); } // 替换原型 + 原型简称 jQuery.fn = jQuery.prototype = { constructor: jQuery } // 给jQuery和原型分别添加extend方法,混入方式 jQuery.extend = jQuery.fn.extend = function( obj ) { for ( var key in obj ) { this[ key ] = obj[ key ]; } } // 给jQuery添加一些静态方法 jQuery.extend({ // 去掉首尾空白字符 trim: function( str ) { // null、undefined、NaN、0、false、'' if ( !str ) { return str; } // 优先使用原生的 if ( str.trim ) { return str.trim(); } return str.replace( /^\s+|\s+$/g, ''); }, // 判断是不是html片段 isHTML: function( html ) { // null、undefined、NaN、0、false、'' if ( !html ) { return false; } // <.> if( html.charAt(0) === '<' && html.charAt( html.length - 1 ) === '>' && html.length >= 3 ) { return true; } return false; }, // 判断是不是html片段 _isHTML: function( html ) { return !!html && html.charAt(0) === '<' && html.charAt( html.length - 1 ) === '>' && html.length >= 3; }, // 判断是不是函数 isFunction: function( fn ) { if ( typeof fn === 'function' ) { return true; } return false; }, // 判断是不是函数 _isFunction: function( fn ) { return typeof fn === 'function'; }, // 判断是不是window isWindow: function( w ) { // null、undefined、NaN、0、false、'' if( !w ) { return false; } if( w.window === w ) { return true; } return false; }, // 判断是不是window _isWindow: function( w ) { return !!w && w.window === w; }, // 判断是不是对象 isObject: function( obj ) { // 防止typeof对null的误判 if ( obj === null ) { return false; } // 如果是object或function,那就是对象 if ( typeof obj === 'object' || typeof obj === 'function' ) { return true; } return false; }, // 判断是不是字符串 isString: function( str ) { if ( typeof str === 'string' ) { return true; } return false; }, // 判断是不是字符串 _isString: function( str ) { return typeof str === 'string'; }, // 判断是不是真数组或伪数组 isLikeArray: function( arr ) { // Function、window、!Object if ( jQuery.isFunction( arr ) || jQuery.isWindow( arr ) || !jQuery.isObject( arr ) ) { return false; } // 判断是不是真数组 if ( ({}).toString.call( arr ) === '[object Array]' ) { return true; } // 判断是不是伪数组 if ( 'length' in arr && ( arr.length === 0 || arr.length - 1 in arr ) ) { return true; } return false; }, ready: function( fn ) { // 先统一判断DOMContentloaded有没有触发, // 通过document.readyState === 'complete'判断 // 如果为true,fn可以直接调用。 // 如果为false,那么判断支不支持addEventListener, // 如果支持,绑定DOMContentLoaded事件 // 如果不支持,使用attchEvent绑定onreadystatechang事件, // 注意,需要在里面判断document.readyState === 'complete'才执行fn。 // 防止fn多次执行。 // DOM已经构造完毕,fn可以直接执行 if ( document.readyState === 'complete' ) { fn(); } // 如果DOM没有构造完毕,那么判断addEventListener是否兼容 else if( document.addEventListener ) { document.addEventListener( 'DOMContentLoaded', fn ); } // 如果不兼容addEventListener,那么采取attachEvent的方式, // 同时事件变为了onreadystatechange,为了防止这个事件多次触发造成的fn多次执行, // 所以需要一个包装函数来进行过滤。 else { document.attachEvent( 'onreadystatechange', function() { if( document.readyState === 'complete' ) { fn(); } } ); } } }); // 这是真正的构造函数,同时把构造函数放在了原型中 var init = jQuery.fn.init = function( selector ) { // null、undefined、NaN、0、false、'' if ( !selector ) { return this; } // function if ( jQuery.isFunction( selector ) ) { // 打包给ready静态方法处理 jQuery.ready( selector ); } // string ==> ( html || selector ) else if( jQuery.isString( selector ) ) { // 为了用户友好体验,先去掉首尾空白字符 selector = jQuery.trim( selector ); // html if( jQuery.isHTML( selector ) ) { // 利用一个临时的div来创建DOM, // 然后把创建好的DOM依次push给实例。 var tempDiv = document.createElement( 'div' ); tempDiv.innerHTML = selector; [].push.apply( this, tempDiv.childNodes ); } // selector else { try { [].push.apply( this, document.querySelectorAll( selector ) ); }catch(e) { // 如果报错了,那么手动补一个length属性,代表没有获取到任何元素 this.length = 0; } } } // array || likeArray else if( jQuery.isLikeArray( selector ) ) { //[].push.apply( this, selector ); 这里,如果selector是自己写的伪数组,而不是系统的伪数组,那么在IE8中会出错,所以我们采用了[].slice.call( selector ) ,把伪数组转变为真数组。 [].push.apply( this, [].slice.call( selector ) ); } // 其它 else { this[0] = selector; this.length = 1; } }; // 替换init的原型为工厂的原型,这样外界就可以通过工厂给实例扩展方法 init.prototype = jQuery.fn; // 暴露工厂和工厂的简称 w.jQuery = w.$ = jQuery; }( window )); // 静态方法测试 console.log($._isFunction([])); console.log($.isWindow( window )); console.log($.isLikeArray( { length: 5 } )); console.log($.isLikeArray( { length: 0 } )); // 入口测试 console.log($([1, 2])); console.log($(' script')); console.log($(' <span>111</span><span>222</span> ')); console.log($({ 0:document.body, length:1 })); // 测试入口对函数的支持 $(function() { console.log($('a')); //再打印这一句 }); console.log($('bb')); //先打印这一句 </script> <div> <a>1</a> <a>2</a> <a>3</a> </div> </body>
2.jQuery中静态方法Each(),数组的forEach(),以及自定义的each()的使用,以及each()中的this指向问题
<script> var obj = { 1: 'aaa', 2: 'bbb', 3: 'ccc' }; var arr = ['xxx', 'yyy', 'zzz']; // jQuery中静态方法each的使用,及其中的this指向,this指的是每一个元素 $.each(obj, function(key, val) { console.log(key, val, this); }); $.each(arr, function(key, val) { console.log(key, val, this); }); // arr的原型方法forEach的使用,注意参数顺序,以及this指向问题window arr.forEach(function(val, key) { console.log(val, key, this); //window }); // function each(obj,fn){ // if ('length' in arr) { // for(var i=0;i<obj.length;i++){ // fn(i,obj[i]); // } // }else{ // for(var key in obj){ // fn(key,obj[key]); // } // } // }; // 自定义方法中的this也是指向window的 // each(arr, function(key, val) { // console.log(key, val, this); //window // }); function each1(obj, fn) { if ('length' in arr) { for (var i = 0; i < obj.length; i++) { fn.call(obj[i], i, obj[i]); } } else { for (var key in obj) { fn.call(obj[key], key, obj[key]); } } }; // 自定义方法中的this也是指向每一元素对应的对象 each1(arr, function(key, val) { console.log(key, val, this); // }); </script>
3.遍历中断,这里最好打个断点看下函数的执行流程,加强对回调函数的理解。
function each1(obj, fn) { if ('length' in obj) { for (var i = 0; i < obj.length; i++) { if (fn.call(obj[i], i, obj[i]) === false) { break; } } } else { for (var key in obj) { if (fn.call(obj[key], key, obj[key])===false) { break; } } } }; // 自定义方法中的this也是指向每一元素对应的对象 each1(obj, function(key, val) { if (val == 'bbb') { return false; } console.log(key, val, this); // }); 打个比方,再调用each1()时,传入了obj和一个函数,这就好比是大boss派了一个保镖去门口监视路过门口的行人obj,保镖的任务是把每个人的编号和T-shirt上的信息告诉大boss,大boss接受到每一个人T-shirt上的信息,发现有个人的T-shirt上写的是‘bbb’,通过对讲机告诉保镖,停止监视false,立刻break.
4.模仿jQuery中map()的实现
<script> var obj = { a: 111, b: 222, c: 333, d: 444 }; var arr = [ 'aaa', 'bbb', 'ccc', 'dddd' ]; /* * jQ的map方法,用来遍历对象或者数组, * 然后把遍历到了val和key值传给回调, * 最后收集回调的返回值,构成新数组返回。 * */ /*console.log($.map(obj, function (val, key) { console.log(val, key, this); return val; }));*/ // map实现 function map( obj, fn ) { /* * 1、先判断obj是不是数组或者伪数组, * 2、如果是,则通过i的方式遍历这个对象 * 3、如果不是,则通过for in的方式遍历这个对象 * 4、在遍历的过程中,把每一次遍历到key和val分别传给回调。 * 5、在给回调传参的时候,需要收集回调的返回值,最后把所有的返回值构成新数组返回。 * */ var i, len, key, result = []; if( 'length' in obj ) { for ( i = 0, len = obj.length; i < len; i++ ) { result.push( fn.call( obj[ i ], obj[ i ], i ) ); } }else { for ( key in obj ) { result.push( fn.call( obj[ key ], obj[ key ], key ) ); } } return result; } console.log(map(obj, function (val, key) { console.log(val, key, this); // return val / 100; })); </script> // 给jQuery的静态方法加入map和each方法,同时,拥有在jQuery的原型中有这两个变量 jQuery.extend({ // 遍历对象或类数组 each: function( obj, fn ) { var i, len, key; if ( jQuery.isLikeArray( obj ) ) { for ( i = 0, len = obj.length; i < len; i++ ) { if ( fn.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } }else { for ( key in obj ) { if ( fn.call( obj[ key ], key, obj[ key ] ) === false ) { break; } } } return obj; }, // map实现 map: function( obj, fn ) { /* * 1、先判断obj是不是数组或者伪数组, * 2、如果是,则通过i的方式遍历这个对象 * 3、如果不是,则通过for in的方式遍历这个对象 * 4、在遍历的过程中,把每一次遍历到key和val分别传给回调。 * 5、在给回调传参的时候,需要收集回调的返回值,最后把所有的返回值构成新数组返回。 * */ var i, len, key, result = []; if( 'length' in obj ) { for ( i = 0, len = obj.length; i < len; i++ ) { console.log('*****',fn.call( obj[ i ], obj[ i ], i )); result.push( fn.call( obj[ i ], obj[ i ], i ) ); } }else { for ( key in obj ) { result.push( fn.call( obj[ key ], obj[ key ], key ) ); } } console.log('-------',result); return result; }, ... }); // 替换原型 + 原型简称 jQuery.fn = jQuery.prototype = { // 遍历实例 each: function( fn ) { return jQuery.each( this, fn ); }, // 通过实例得到一个新数组 map: function( fn ) { return jQuery.map( this, fn ); }, ... }
相关文章推荐
- jQuery的一些简单知识点(一)
- JQuery的一些简单使用
- Jquery的一些知识点
- Jquery的一些简单使用记录
- 一些简单,但是常用到,又容易遗忘的知识点
- 下面简单使用Jquery来操作iframe的一些记录,这个使用纯JS也可以实现。
- JQuery一些简单常用的方法
- spring一些简单小注意知识点
- 学习jquery的一些简单运用
- jQuery 进行一些简单的表单验证
- jQuery的一些一些小知识点的用法的介绍
- jquery和validate的一些简单用法笔记
- 总结一下一些简单但是自己又不清楚的知识点(华为题目)
- jquery一些简单的小技巧
- C#,一些非常简单但应该知道的知识点
- 原生JS取代一些JQuery方法的简单实现
- jQuery 中一些细节知识点2(本文会持续更新)
- jquery项目中一些比较常用的简单方法
- jquery 一些简单代码
- javascript中一些简单的知识点