1. 复习题
- 考点:
- 类的原型如果重新被赋给新的地址,此时里面已经不再有constructor属性;
- 对象中调用属性时,如果该属性中存在this,那此时this指向该对象;
- 原型链的考察,如果自己私有属性中找不到目的属性,需要通过原型链向所属类的原型上查找,如果查找到基类的时候,还没有,则返回undefined;
- undefined与数字进行相加,非法运算,返回NaN;
<script>
function Fn(num) {
this.x=this.y=num;
}
Fn.prototype={
x:20,
sum:function(){
console.log(this.x+this.y);
}//Fn类的原型地址被改变,重新赋值新地址;
};
var f=new Fn(10);
console.log(f.sum===Fn.prototype.sum);//结果true;指向同一个地址,所以严格比较为true;
f.sum();//结果为20;
//此时this指向f实例对象;
Fn.prototype.sum();//结果为NaN;考察原型链,Fn对象上的属性存在x,但是不存在y属性,Fn原型的所属类,为基类,基类原型上也不存在y属性,所以会返回undefined;与数字相加为NaN;
//此时this指向Fn.prototype对象;
console.log(f.constructor);//因为已经对Fn.prototype对象进行了重新赋值,添加了新地址,所以新地址中不再有constructor属性;
//此时f的Fn类的原型上没有了constructor属性,所以还要向它的所属类的原型去找,则找到基类Object上的constructor属性,属性值为基类:"ƒ Object() { [native code] }";
Fn.prototype.constructor=Fn;//给Fn的原型设置新的constructor属性;
console.log(f.constructor);//Fn构造函数信息;返回Fn类:"ƒ Fn(num) {this.x=this.y=num;}";
</script>
2. 数组求平均值
- 平均值定义:在数组元素中去掉最大值和最小值,剩下的元素求和取平均值;
- 考点:
- 数组平均数的定义,去掉最大值,最小值,然后剩下的元素求和取平均值;
- 数组sort()排序,pop()删除最后一项,shift()删除第一项;
- join("符号"),将数组用符号连接成字符串;
- eval("字符串")将字符串作为JS代码执行;
- 数字.toFixed(位数):将数字四舍五入保留几位小数;
- 代码:
<script>
var ary=[37,27,45,67,87,54,23,45,65,3,56,98,30];
function average(ary){
ary.sort(function(a,b){return a-b});
ary.pop();
ary.shift();
var rww=eval(ary.join("+"))/ary.length ;
return rww.toFixed(3);//将数字结果保留三位小数,四舍五入;
}
var res=average(ary);
console.log(res);
</script>
3. 类数组转数组
- 原型上的属性方法解读:
- 每一个类,都有自己的原型,自己原型上的东西,别人不能用
- 深层去解读一下,原型上的属性或是方法,原型上会有属性名,属性值为函数的定义阶段,当使用原型上的某个属性时,获得是函数定义地址,所以需要加(),就是执行函数,也称为方法;
- 原型上的属性在定义阶段,函数里面会进行很多设置,设置是针对谁?针对的是实例对象,也就是this,函数在定义的时候,就默认将实例对象传进去了,一切的操作都是对this实例对象进行开刀,即进行其他的操作;
- 数组类Array的原型上存在系统属性:slice,concat等,所对应的属性值为一个定义函数,里面所设置的都是对象实例this,要想不属于数组类去享受这个方法,就可以将this改变为那个类;
- 类数组具有数组的特征,属性和方法样式一样,但是不属于数组类,不能去获得数组类原型上的属性方法;所以就需要通过call,apply,bind这些方法来将类数组对象变为数组类原型上属性方法中的this实例对象;这样就可以享受封装的方法了;
- 类数组转化为数组的方法:
- 代码:
var ary1=Array.prototype.slice.call("类数组")
;
- 实质:就是获取数组类原型上的slice属性,将其实例对象this改为类数组对象;
- 只要能通过原型链获取数组类原型上的slice属性就行,所以也可写成
var ary1=[].slice.call("类数组")
- 此时ary1就是类数组转化为的真正数组,属于数组类Array,同时享用数组类原型上的属性方法;
- 方法解读:利用类数组arguments来解读类数组转数组的方法;
<script>
var ary=[12,3,4,54,56,34,55];
var ary1=ary.slice();//结果克隆ary数组,说明slice()方法在克隆时,可以不传参;
/* var ary1=ary.slice(0);//效果一样,slice()方法在克隆时,可以传入实参0;*/
console.log(ary1);
function mas() {
//arguments就接受了所有的实参,实参作为元素形成一个类数组;
var res=Array.prototype.slice.call(arguments);//实现类数组转数组;
console.log(res);
/* var res=Array.prototype.slice.call(arguments,0);//对应上面的传入0的实参;*/
//此时res就是一个真正的数组,属于数组类Array,同时享用数组类上面的属性方法;
var ree=res.concat(45);
console.log(ree);
}
mas.apply(null,ary);//apply作用,就是将数组中的元素作为实参传入函数中;
</script>
- 类数组有两种
- 类数组转数组的封装方法,在不同的浏览器中都适用;
<script>
//需求:将类数组转化为数组,注意兼容性问题
//参数:类数组(arguments,htmlCollection);返回值:数组
function makeArray(arg){
try{//当浏览器兼容的时候,执行下面代码不报错,则不会执行catch语句;
return Array.prototype.slice.call(arg);
}catch(e){//当浏览器不兼容的时候,会报错,然后执行catch语句
var ary=[];
for(var i=0; i<arg.length; i++){
ary.push(arg[i]);
}
return ary;
}
}
</script>
4. 浏览器的异常捕获
5. jsonParse封装
- window为Window的实例对象,而JSON为window的私有属性;
- JSON为系统window的属性,JSON上有两个属性方法,parse()和stringify()
- JSON.parse(strJson):把JSON格式的字符串strJson转化为JSON格式的对象;
- JSON.stringify(objJson):把JSON格式的对象转化为JSON格式的字符串;
- JSON格式对象与普通对象的区别是:JSON格式的对象中的属性名一定用双引号"";属性值如果是数字可以不加引号;
- 注意:兼容性问题:在IE7下,window的不存在JSON属性;所以window.JSON返回的是undefined;
<script>
var obj={name:"guobin",age:8};//普通对象
var objJson1={"name":"guogin","age":26};//JSON
//JSON中属性名,属性值都用双引号,如果是数字可以不加;
var objJson=[{"name":"guogin","age":26},{"name":"guogin1","age":26},{"name":"guogin2","age":26},];//数组对象;
console.log(objJson);
var mass=JSON.stringify(objJson);//转化为字符串;
console.log(mass);
var mss=JSON.parse(mass);//转化为对象;
/*//JSON在IE浏览器中不支持;
//解决方法:用eval();
var mss1=eval("("+mass+")");*/
console.log(mss);
</script>
6. 工具库封装
- 考点:
- utils工具库是新建的一个JS文件,用于调用属性方法;
- 里面格式使用自执行函数,避免添加全局变量
- 代码中添加完键值对后,在上面输入
/**
然后按回车键,就会自动添加注释;
- 两种方法的对比,体现了
try..catch..
方法与if..else..
方法的使用情景
-
try..catch..
方法用在不同浏览器的兼容性问题中,即有些浏览器支持,有些浏览器会报错;
- 在运行时,在支持的浏览器下执行try命令,在不支持的浏览器下执行catch命令;
-
if...else..
方法,用在不同浏览器的兼容性问题中,即有些浏览器支持,有些浏览器不支持某一属性,会返回undefined,但不会报错;
- 判断条件一般为是否存在该属性,如果存在就执行if语句,如果不支持就执行else语句;
<script>
//utils工具库
//自执行函数的目的是形成一个私有的作用域,避免添加全局属性;
//里面return返回的是一个对象;
var utils=(function () {
return {
/**
* 类数组转化为数组的封装方法
* @param arg(arguments,htmlCollection)
* @returns {Array}(返回数组)
*/
makeArray:function(arg){
var ary=[];
//此时用try..catch..方法,是因为htmlCollection类数组,在IE浏览器中不能修改this,会报错;
try{
ary=Array.prototype.slice.call(arg);
}catch(e){
for(var i=0; i<arg.length; i++){
ary.push(arg[i]);
}
}
return ary;
},
/**
* 把JSON格式的字符串转化为JSON格式的对象
* @param strJson
* @returns {Object}
*/
jsonParse:function (strJson) {
//此时用if..else..,不用try..catch..的原因是:在IE7中window不存在JSON属性,所以返回的是undefined,不会报错,只有当报错的时候,才会只用try..catch..;
if(window.JSON){//判断条件可以是"JSON" in window;属性从属判断;
return JSON.parse(strJson);
}else{
return eval("("+strJson+")");//eval()的坏处会存在注入攻击;
}
//三目写法:return window.JSON ? JSON.parse(strJson) : eval("("+strJson+")");
}
}
})();
</script>
7.sort排序深入解读
- sort排序
ary.sort(funtion (a,b){
return a-b;//可以写成(b-a)*-1;
})
<script>
var ary=["2成龙","4胡歌","1李连杰","5阿祖","3刘亦菲"];
//利用sort()对数组进行排序
//需求1:通过每个字符串中的数字进行排序;
//知识点:字符串转化为数字的非严格转换parseInt()或parseFloat()
ary.sort(function (a,b) {
a=parseInt(a);
b=parseInt(b);
return a-b;
});
console.log(ary);//结果为["1李连杰", "2成龙", "3刘亦菲", "4胡歌", "5阿祖"];
</script>
- DOM映射:html页面中的DOM结构,跟通过JS获取到的元素集合htmlCollection之间,存在一一对应的关系
- 利用appendChild()方法,其实目的是剪切作用,把排完序的元素结合,插入到oul元素节点的最后一个子节点,此时DOM结构中,相对应的元素,会剪切到最后一位;
- 改变DOM结构方法:1)appendChild();2)insertBefore();3)removeChild();4)replaceChild();
- 实例需求1:利用sort()方法,将DOM结构中的每个li元素,通过内容中的数字进行从小到大的顺序排列;
//需求:利用sort()方法,将DOM结构中的每个li元素,通过内容中的数字进行从小到大的顺序排列;
<body>
<ul>
<li>1我是列表</li>
<li>3我是列表</li>
<li>2我是列表</li>
<li>4我是列表</li>
</ul>
<script src="utils.js"></script>
<script>
var ali=document.getElementsByTagName("li");
var oul=document.getElementsByTagName("ul")[0];
//把类数组,转化为数组
var ary=utils.makeArray(ali);
//利用sort()进行列表排序,按照里面的内容数字排列;
ary.sort(function (a,b) {
a=parseInt(a.innerHTML);
b=parseInt(b.innerHTML);
return a-b;
});
//改变DOM页面结构,方法:appendChild(),insertBefore()
for(var i=0; i<ary.length; i++){
oul.appendChild(ary[i]);
}
</script>
- 实例需求2:利用sort()方法,将DOM结构中的每个li元素,通过内容文字拼音的首字母进行从a-z顺序排序,利用localeCompare()方法;
<body>
<ul>
<li>李连杰</li>
<li>成龙</li>
<li>甄子丹</li>
<li>杨紫琼</li>
</ul>
<script src="utils.js"></script>
<script>
var ali=document.getElementsByTagName("li");
var oul=document.getElementsByTagName("ul")[0];
//把类数组,转化为数组
var ary=utils.makeArray(ali);
//利用sort()进行列表排序,按照里面的内容数字排列;
ary.sort(function (a,b) {
a=a.innerHTML;
b=b.innerHTML;
return a.localeCompare(b);//按照汉字拼音的首字母的从a-z进行排序
//return a.localeCompare(b)*-1;//按照汉字拼音的首字母的从z-a进行排序
//return b.localeCompare(a);//也可写成这种形式,按照汉字拼音的首字母的从z-a进行排序
});
//改变DOM页面结构,方法:appendChild(),insertBefore()
for(var i=0; i<ary.length; i++){
oul.appendChild(ary[i]);
}
</script>
- 注意:localeCompare()方法运用不准确;
8. 插入页面的几种方式
- 字符串拼接;最简单,最常用,字符串插入页面用innerHTML;
- 问题:如果页面中以前的元素在添加之前身上有事件,当重新进行字符串拼接后,重新再插入页面,那么他们以前身上的事件就都不存在了;
<body>
<div><span>姓名</span><span>年龄</span></div>
<script>
var ary=[
{"name":"guobin","age":26},
{"name":"guoyang","age":19},
{"name":"guodan","age":18},
{"name":"guoyao","age":14},
{"name":"guorunze","age":2}
];
//1.字符串拼接;最简单,最常用,字符串插入页面用,innerHTML;
//问题:如果页面中在添加以前的元素身上有事件,当重新进行字符串拼接后,重新再插入页面,那么他们以前身上的时间就都不存在了;
var aDiv=document.getElementsByTagName("div");
aDiv[0].onmouseover=function () {
this.style.backgroundColor="pink";
};
aDiv[0].onmouseout=function () {
this.style.backgroundColor="";
};
var str="";
for(var i=0; i<ary.length; i++){
var cur=ary[i];
str+="<div><span>"+cur.name+"</span><span>"+cur.age+"</span></div>"
}
//2.插入到页面中
document.body.innerHTML+=str;//document.body指的是body元素节点;
//此代码意思是,将原来的字符串从页面上拿出来,然后与新的字符串进行拼接,然后再重新插入页面中;此时原来设置的事件都不存在了;必须重新设置;
</script>
</body>
- DOM动态插入:新建元素及内容,每建一个就插入一个到页面
- 问题:每新建一个odiv就需要向页面中插入一次,如果数组中对象个数很多,就会频繁插入页面,会产生影响;
<script>
//2.DOM动态插入
for(var i=0; i<ary.length; i++){
var cur=ary[i];
var odiv=document.createElement("div");
for(var attr in cur){
var ospan=document.createElement("span");
ospan.innerHTML=cur[attr];
odiv.appendChild(ospan);
}
document.body.appendChild(odiv);
}
</script>
- 文档碎片:对页面的优化,简化DOM操作,就是把所有创建的odiv先放在文档碎片中,最后一起插入到页面中,当插入完后,将其释放,达到性能优化的目的;
- 优点:创建文档碎片,将每次新建的odiv,放在文档碎片中,最后新建完毕,统一插入到页面中,减少频繁操作;当插入完毕后,对文档碎片清除,性能优化;
- 创建文档碎片:
var frg=document.createDocumentFragment()
;
- 清除内存:
frg=null
;
<body>
<div><span>姓名</span><span>年龄</span></div>
<script src="data.js"></script>
<script>
var frg=document.createDocumentFragment();//新建一个文档碎片,用于接收每次创建的odiv元素;
for(var i=0; i<ary.length; i++){
var cur=ary[i];
var odiv=document.createElement("div");
for(var attr in cur){
var ospan=document.createElement("span");
ospan.innerHTML=cur[attr];
odiv.appendChild(ospan);
}
frg.appendChild(odiv);
}
document.body.appendChild(frg);//将文档碎片插入到body元素中;
frg=null;//赋值null,将文档碎片删除,性能优化;
</script>
</body>