12/13/2016 3:29:39 PM
将之前的笔记1212号的干掉了,尽进行根据代码进行总结
jQ原型上的核心成员
- jquery 属性,获取jQ的版本
- length 属性,实例的length属性默认值
-
get方法,传参按照指定下标获取对应的DOM元素,不传参把jQ对象转换为数组返回
- eq 方法
- first 方法
- last 方法
- push
- sort
- splice
- toArray
- slice
- pushStack
- end
- each
- map
jquery 属性
- 作用
- 获取jq的版本
- 代码
console.log($().jquery);//3.1.0
$().length
- 作用
- 0 是在原型length:0
- 是为了保持完整性
-
执行代码
console.log($().length);//0
get方法
- 作用
- 不传参把jQ对象转换为数组返回
- 传参按照指定下标获取对应的DOM元素,
- 实现
-
jq中的实现
/* * get方法 * 不传参把jQ对象转换为数组返回 * 传参按照指定下标获取对应的DOM元素, * */ console.log($('li').get()); console.log($('li').get(0)); console.log($('li').get(5)); console.log($('li').get(-1));//获取最后一个 console.log($('li').get(1,2));//只会接收一个参数,第二个参数会被忽略
-
- 进行框架封装的
- 思路
- 不传参数,借用slice方法把实例对象转换为数组返回
- 传参数,进行根据下标值来返回一个dom对象
-
代码
get : function(i){ /* * 思路: * 1. 不传参数,借用slice方法把实例对象转换为数组返回 * 2. 传参数,进行根据下标值来返回一个dom对象 * */ if(arguments.length==0){ return [].slice.call(this); }else{ /* * 根据参数的下标 * 1. 如果下标大于0,直接进行 因为是伪数组对象[下标值] * 2. 如果是小于0,直接进行从长度+i * */ if(i>=0){ return this[i]; }else{ return this[this.length+i] } } }, _get : function(i){ if(arguments.length==0){ return [].slice.call(this); }else{ return i>=0?this[i]:this[this.length+i]; } }
- 思路
eq方法
- 作用
- eq返回的是jq对象
- 没有参数,直接进行返回一个空对象
- 有参数,进行返回获得的jq对象
- eq返回的是jq对象
-
jq中eq的返回结果
/* * eq返回的是jq对象 * 1. 没有参数,直接进行返回一个空对象 * 2. 有参数,进行返回获得的jq对象 * */ console.log($('li').eq());//jQuery.fn.init[0] console.log($('li').eq(0));//jQuery.fn.init[1] console.log($('li').eq(9));//jQuery.fn.init[0] console.log($('li').eq(undefined));//jQuery.fn.init[0] - 封装eq和first和last
- 实现eq方法first和last
- 思路
- eq参数个数
- 如果个数为0,直接进行返回一个空的jq对象,所以不需要判断
- 直接进行判断
- eq参数个数
-
代码
eq : function(i){ /* * 参数的个数 * eq参数个数 * 1. 如果个数为0,直接进行返回一个空的jq对象,所以不需要判断 * 2. 直接进行判断 * */ if(i>=0){ return jQuery(this[i]); }else{ return jQuery(this[this.length+i]); } }, /*_eq : function(i){ /!* * 思路: * 1. 没有参数,直接进行返回一个空jq对象;或是 * 2. 有参数,进行和get一样,就是返回的时候进行包装一下成jq对象 * *!/ return jQuery(this.get(i)); },*/ first : function(){ return this.eq(0); }, last : function(){ return this.eq(-1); }
- 思路
- 实现eq方法first和last
toArray方法
- 作用
- 转换成数组对象
-
jq的返回结果
//转换成数组对象 console.log($('li').toArray()); var lis = document.querySelectorAll('li'); //进行改变数组的slice的this指向 //进行使用slice,返回的是一个数组的对象 //,dom的this,指向前面的[]的slice方法,就可以使用数组的方法 console.log([].slice.call(lis)); - 框架的封装jq的
-
代码
toArray : function(){ return [].slice.call(this); } /*测试toArray的方法*/ console.log($('li').toArray());
-
slice方法
- 先列举jq中的方法
- slice 方法,按照指定下标截取部分元素,然后包装成jQ实例返回
-
检验JQ中的slice
//先列举jq中的方法 /* *slice 方法,按照指定下标截取部分元素,然后包装成jQ实例返回 * */ //什么也不写, console.log($('li'));//就是获取li标签的伪数组 console.log($('li').slice());//也是返回li标签的伪数组 console.log($('li').slice(1));//就是从第一个开始进行截取到最后 //就是第二个[li, prevObject: jQuery.fn.init[3]],后面的这个就是上级的 console.log($('li').slice(1, -1)); /* 到end()的时候再看 //[li, li, li, prevObject: jQuery.fn.init[1]]就是上一级的链条上的数据 console.log($('li').slice(1, -1).prevObject); //[li, li, li, prevObject: jQuery.fn.init[1]] 和上面的代码的执行结果是一样的 console.log($('li').slice(1, -1).end());*/ var arr = [1,2,7,9]; //数组中的什么也不传,进行返回的就是数组的对象 console.log(arr.slice());//[1, 2, 7, 9] console.log(arr.slice(1));//[2, 7, 9] 对的,就是从第一个开始截取到最后 console.log(arr.slice(1,-1));/* 2 7 就是左闭合右开*/ //在jq中,就是将剩余的数组包装成jq对象 /* * 总结: * 1.通过js使用的slice * 2.再包装成jQ对象 * */ - 总结
- 通过js使用的slice
- 再包装成jQ对象
- 框架封装
- 思路
- 直接进行调用数组的slice
- 再包装成jQ对象
-
实现代码
slice : function(start,end){ /* *思路: * 1. 直接进行调用数组的slice * * 2. 再包装成jQ对象 * */ //使用call转换this的指向,然后传参start,end,这个是给slice进行的传参 return jQuery([].slice.call(this,start,end)); } -
测试代码
/* * 测试在jq中封装的slice方法的返回值 * */ //什么也不传,和直接获取$('li')是一样的 console.log($('li')); console.log($('li').slice()); console.log($('li').slice(1));//取到的是2和3 console.log($('li').slice(1,-1));//取到的是2
- 思路
push、sort、splice方法
- 作用
- push 方法,给实例添加新元素,返回最新的length长度
- sort 方法,对实例中的数据进行排序,返回排序后的实例
- splice 方法,按照指定下标指定数量删除元素或插入元素,返回被删除的元素
-
jq中的方法的检验
/* 返回的就是伪数组 * 7、push 方法,给实例添加新元素,返回最新的length长度 * 8、sort 方法,对实例中的数据进行排序,返回排序后的实例 * 9、splice 方法,按照指定下标指定数量删除元素或插入元素,返回被删除的元素 * */ /*console.log($('li'));//长度是3个li console.log($('li').push($('span')));//4*/ var arr = [1,3]; console.log(arr.push(5));//返回的是长度3 /* * 返回的是排序li的innerHTML进行的排序 * */ /*console.log($('li').sort(function (a, b) { return a.innerHTML < b.innerHTML; }));*/ /* * [9, 2, 1, 0] * */ /* var arr = [1,9,0,2]; console.log(arr.sort(function (a, b) { return a < b; }));*/ /* * splice * splice 方法,按照指定下标指定数量删除元素或插入元素,返回被删除的元素 * */ /* var $li = $('li'); //将下标为1,长度为1的数组进行删除,并且插入2, 8, 9 console.log($li.splice(1, 1, 2, 8, 9)); console.log($li);*/ -
封装jq中的push sort splice
push : function(){ /* * 思路: * 1. 直接进行调用数组的push方法,也是返回的是长度 * 2. 改变this的指向数组的方法,就可以调用数组的push * */ return [].push.apply(this,arguments); }, sort : function(fn){ return [].sort.call(this,fn); }, splice : function(){ //把obj里面的参数传值给splice的参数 return [].splice.apply(this,arguments); }, /*这种写法是直接将数组的push或是别的方法给这个实例的属性上*/ _push: arr.push, _sort: arr.sort, _splice: arr.splice -
对封装的代码进行测试的代码
/* * 测试push * 测试sort * */ console.log($('li').push($('span'))); //测试的是对所有li标签里面的内容进行从大到小的排序 console.log($('li').sort(function (a, b) { return a.innerHTML < b.innerHTML; })); /*测试splice*/ var $li = $('li'); //这个直接打印时删除的数据 console.log($li.splice(1, 1, 90));//进行删除下标为1的元素,并且在这个位置添加90 /* * 0:li 1:90 2:li * */ console.log($li);
方法的借用的几种方式
- 方法借用
- 第一种方式是通过call或是apply的方式,让fn内部的this指向p对象,
- 第二种方式是直接给对象添加一个fn属性,这个属性的值是函数
-
代码
/* * 通过上下文调用模式直接进行改变this的指向 * * */ /*var obj = {}; //将数组的this指向obj, //前面[]就是数组对象,也就是实例 [].push.call(obj,1); //Object {0: 1, length: 1} console.log(obj);*/ /* * 把数组对象的push方法添加到obj身上 * */ var obj = {}; // console.log(obj.push());//obj.push is not a function(…) /* * * 直接将实例的push方法,给obj的push属性 * 则obj就是push 得到的函数 * */ obj.push = [].push; console.log(obj); //这句代码也完成了push方法的执行,同时push内的this同样为obj obj.push(2); //Object {0: 2, length: 1} console.log(obj); /* * 进行给对象添加一个函数的值 * */ function fn(){ console.log(this); } var p = { name : 'waxun' }; //第一种方式是通过call或是apply的方式,让fn内部的this指向p对象, //Object {name: "waxun"} //fn.call(p); //第二种方式是直接给对象添加一个fn属性,这个属性的值是函数 p.fn = fn; //Object {name: "waxun"} p.fn();
end方法
- 作用
- end 方法,返回上一级链(链式编程中上一个jQ对象)
-
使用jq中的end进行找回断之前的链式
/* end 方法,返回上一级链(链式编程中上一个jQ对象) * */ /* * 给下标为li进行设置背景色 * 这样试用eq得到的li就是下标为1的li的元素 * 需求: * 想实现链式编程,就需要找回原来直接进行获取li的个数,在这里是三个 * */ /* console.log($('li').eq(1).css({ backgroundColor: 'red' })); /!* * 解决上面的需求 * * 要想返回上级链(就是找回上一个jQ对象),需要调用end方法 * *!/ //[li, li, li, prevObject: jQuery.fn.init[1]] console.log($('li').eq(1).css({ backgroundColor: 'red' }).end());*/ - 需求
- 目前有两个对象,可以通过一个对象找到另一个对象
- 解决办法
- 在一个对象的属性上添加一个可以找到第二个对象的标志
- 就可以通过一个对象可以找到另一个对象
- 要有关联性
-
实现代码
var obj1 = { name : 'waxun' }; var obj2 = { prevObj : obj1 }; //通过obj2 可以找到 obj1 //Object {name: "waxun"} console.log(obj2.prevObj); //需求: 要提供一个end方法供调用者使用,对象调用end,就会得到第一个对象 //给obj2自己添加一个end()方法 obj2.end = function(){ return this.prevObj; } //Object {name: "waxun"} console.log(obj2.end());
- 什么情况下可以调用end方法
- 就是 返回值是jQ对象的,可以通过end进行找出上级链
-
代码解释
/*就是 返回值是jQ对象的,可以通过end进行找出上级链 * 报错,因为get返回的是原生DOM元素, * 原生DOM元素并没有继承jQ的原型,所以无法访问end方法。 * 总结: * 链式编程如果断掉了, * 并且返回值不是jQ实例, * 那么链就无法再通过end方法找回上级链了。 * */ //$(...).get(...).end is not a function(…) console.log($('li').get(0).end());
- 框架中实现pushStack和end的关联进行实现链式编程
-
实现pushStack和end方法
slice : function(start,end){ /* *思路: * 1. 直接进行调用数组的slice * * 2. 再包装成jQ对象 * */ //使用call转换this的指向,然后传参start,end,这个是给slice进行的传参 //return jQuery([].slice.call(this,start,end)); /* * 因为slice改变了链式结构,并且返回的是jq对象,所以需求是 * 可以通过end的方式进行找回断掉之前的数据, * 就需要断掉之前的数据进行存储一下子 * * 这边slice返回的也是jQ对象,所以也给pushStsck传值过去一起处理就可以 * */ /* var arr = [].slice.call(this,start,end); return jQuery(arr);*/ var arr = [].slice.call(this,start,end); //交给pushStack去转成jQ对象,并且添加一个存储这个调用this的属性 return this.pushStack(arr); } /*实现pushStack方法,用来记录上级链的关联*/ pushStack : function(arr){ //$new 进行将调用传来的值转换成jQ对象,并且加上没改变链条之前的数据 var $new = jQuery(arr); $new.preObj = this;//谁调用的pushStack,这个this就指向谁 return $new; }, /*实现end方法*/ end : function(){ return this.preObj; }
-
-
测试框架中写到slice关联pushStack和end
/* * 测试end() 和 pushStack() * */ /*通过slice得到数组下标从0开始,到2结束,左闭合右开的取值数据, 两种方式得到上级的链式结构上的数据 得到的是jq对象,可以通过直接找自己身上的preObj属性 和通过end()方法找$('li').slice(0, 2)截取后得到的两个li对象上的preObj属性*/ console.log($('li').slice(0, 2)); //找回变之前的链条 console.log($('li').slice(0, 2).preObj); console.log($('li').slice(0, 2).end());
jQ原型上的each方法
- jQ原型上的each方法
- 用来遍历所有的元素
- 要求传入一个函数,这个可以接收两个参数
- 第一个参数为元素的下标,第二个参数为元素
-
jq的实现
/* * 0 <li>1</li> * 1 <li>2</li> * 2 <li>3</li> * */ /*$('li').each(function(index,val){ console.log(index,val); });*/ - jq中的each中的this
-
代码及注释
/* * jQ中的each中,参数是index,val, * 而遍历时this指向的了val的值 * */ /*$('li').each(function(index,val){ console.log(index,val,this); })*/
-
-
js中实现each并且改变this的指向
/** * * @param obj 传入的对象 * @param fn 执行完each之后的回调函数 * * 注意: * 1.回调函数中this默认的指向是window * 2.jq中this的指向是和val值一样的 * 2.1 通过call进行改变 */ function each(obj,fn){ if(obj instanceof Array){ for(var i=0;i<obj.length;i++){ //这是函数调用模式,this指向window //fn(i,obj[i]); //要想this指向val,需要利用call或apply fn.call(obj[i],i,obj[i]); } }else{ for(var key in obj){ //函数调用模式指向的是window //fn(key,obj[key]); //改变this指向 fn.call(obj[key],key,obj[key]); } } } - each方法可以中断遍历
- jQ的each方法,执行传入的回调时,会判断回调的执行结果,
- 如果结果为false,那么each会自动中断遍历
- 注意:这个中断是由each来实现和控制的的。
-
模仿jq中的each中断遍历
/** * 功能: 模仿jQ中,如果回调函数返回的结果是false,就中断遍历 * * @param obj 传入的对象 * @param fn 执行完each之后的回调函数 * */ function each(obj,fn){ if(obj instanceof Array){ for(var i=0;i<obj.length;i++){ //如果回调函数执行的结果为false,就中断遍历 if(fn.call(obj[i],i,obj[i])==false){ break; } } }else{ for(var key in obj){ //如果回调函数执行的返回值为false,就中断遍历 if(fn.call(obj[key],key,obj[key])==false){ break; } } } } var arr = [1,'kaguo',false,'waxun']; /* * 执行结果 * 0 1 * 1 "kaguo" * 返回给回调函数一个false,就中断了遍历 * */ each(arr,function(index,val){ if(val==false){ return false; } console.log(index,val); });
-
包装each
/* * 添加each方法 : * 1. 参数是obj和fn回调函数,通过fn进行返回index和val * 1.1 判断是不是数组或是伪数组,如果是,使用for循环遍历 * 1.2 如果不是,进行使用for..in遍历 * 2. each中this的指向是和val的值一样,所以要通过call进行改变this的指向 * 3. 如果回调函数返回的是false,就中断遍历 * */ function each(obj,fn){ if(isObj(obj)=='Array'||isArrayLike(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; } } } //为了jq链式编程的完整性 return obj; }; each : function(fn){ return each(this,fn); } -
测试代码
/* * 测试each方法的使用 * 1. 真数组 * 2. 遍历伪数组 * 3. 遍历其他 * */ $('li').each(function(index,val){ console.log(index,val); }); /* * 判断内容为空的时候,后面的内容不进行输出 * */ //只输出了前两个,因为第三个为空,后面的不进行输出 //进行打印最外层的是each返回了一个调用自己的对象,进行链式的完整性 console.log($('li').each(function (index, val) { //里面直接是 if (val.innerHTML == false) { return false; } console.log(index, val); }));
for in
- 作用
- for in即可以遍历对象,也可以遍历数组
- for in 有一个特点,就是能够遍历出对象所继承的属性(这个属性必须是可枚举的)
-
代码(主要看被继承的也打印出来了)
/* * 打印结果 * 0 wa * 1 xun * hiN 被继承的 * * * name waxun * age 12 * hiN 被继承的 * */ Object.prototype.hiN = '被继承的'; for(var key in arr){ console.log(key,arr[key]); } for(var key in obj){ console.log(key,obj[key]); }
call和apply的this问题
- 非严格模式下
- 如果call的是基本数据类型,那么call会自动把他包装成对象类型,
- 如果call的是undefined或null,那么call会自动转换为window
- 严格模式下
- call什么,就是什么
-
代码
function fn(){ console.log(this); } fn();//window 函数调用模式 this指向的是window fn.call(undefined);//this打印的是window fn.call(null);//this打印的是window fn.call(1);//this打印的是Number 基本的包装类 fn.call('abc');//String fn.call([1,2]);//Array[2]
jQeach方法的返回值
- jQ中,遍历谁,就返回谁
- 遍历body,返回的就是body
-
代码
<ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script> /* * jQ中,遍历谁,就返回谁 * 1. 遍历body,返回的就是body * * */ /*$('body').each(function(){ console.log(this); this.style.backgroundColor = '#666'; }); */ //将body的宽度打印出来 console.log($('body').each(function () { this.style.backgroundColor = "#666"; }).css('width'));//1350px </script>
12/13/2016 4:04:12 PM