js:2.

JS第二周

JS中的数组类型转换汇总
[基本数据类型]
number 数字
string 字符串
boolean 布尔
null 空
undefined 未定义
[引用数据类型]
object类型 
普通对象
数组对象 (Array)
正则对象 (RegExp)
日期对象 (Date)
数学函数 (Math)
function 函数
把其它数据类型转换为number类型
1、发生的情况
isNaN检测的时候:当检测的值不是数字类型,浏览器会自己调用Number方法把它先转换为数字,然后再检测是否为非有效数字
1.isNaN('3')=>false
2.  Number('3')->3
3.  isNaN(3)->false
4.
5.isNan('3px')=>true
6.    Number('3px')->NaN
7.    isNaN(NaN)->true
基于parseInt/parseFloat/Number去手动转换为数字类型
数学运算:+ - * / %,但是”+”不仅仅是数学运算,还可能是字符串拼接
1.'3'-1 =>2
2.    Number('3')->3
3.    3-1=2
4.
5.'3px'-1 =>NaN
6.
7.'3px'+1 =>'3px1' 字符串拼接
8.
9.var i='3';
10.i=i+1; =>'31'
11.i+=1;  =>'31'
12.i++;    =>4   i++就是单纯的数学运算,已经摒弃掉字符串拼接的规则
在基于”==”比较的时候,有时候也会把其它值转换为数字类型
2、转换规律
1.//=>转换为数字类型的时候浏览器默认都是用Number()方法
2.【把字符串转换为数字】
3.只要遇到一个非有效数字字符,结果就是NaN
4.''->0
5.'   '->0(空字符串里面是空格)
6.'\n' ->0 换行符(Enter)
7.'\t' ->0 制表符(Tab)
8.
9.【把布尔转换为数字】
10.true ->1
11.false ->0
12.
13.【把没有转换为数字】
14.null ->0
15.undefined ->NaN
16.
17.【把引用类型值转换为数字】
18.首先都先转换为字符串(toString),然后再转换为数字(Number)
把其他类型值转换为字符串
1、发生的情况
基于alert/confirm/prompt/document.write等方法输出内容的时候,会把输出的值转换为字符串,然后再输出
1.alert(1) =>'1'
基于”+”进行字符串拼接的时候
把引用类型值转换为数字的时候,首先会转换为字符串,然后再转换为数字
给对象设置属性名,如果不是字符串,首先转换为字符串,然后再当做属性存储到对象中(对象的属性只能是数字或者字符串)
手动调用toString/toFixed/join/String等方法的时候,也是为了转换为字符串
1.var a=Math.PI;
2.Math.PI.toFixed(2) ->'3.14'
3.
4.var ary=[1,45,2,34,34];
5.ary.join("+")
6.'1+45+2+34+34';//返回值,原有数组不变
7.
2、转化规律
1.//=>调用toString方法
2.【除了对象,都是你理解的转换结果】
3.1 ->'1'
4.NaN ->'NaN'
5.null ->null
6.[] ->''
7.[12] ->'12'
8.[12,23] ->'12,23'
9.
10.【对象】
11.{name:"zhufneg",age:9}  ->'[object Object]'
12.{} ->'[object Object]'
13.不管时候啥样的普通对象,最后结果都一样
14.
在控制台调用toString方法的时候,具体的值要套上括号,变量不用套 

把其它值转换为布尔类型
1、发生的情况
基于!/!!/Boolean等方法转换
条件判断中的条件最后都会转换为布尔类型
…
1.if(n){
2.    //=>把n的值转换为布尔验证条件真假
3.}
4.
5.if('3px'+3){
6.    //=>先计算表达式的结果'3px3',把结果转换为布尔true,条件成立
7.}
2、转换的规律 
只有0/NaN/”“/null/undefined五个值转换为布尔的false,其余都是转换为true
特殊情况:数学运算和字符串拼接
1.//=>当表达式中出现字符串,就是字符串拼接,否则就是数学运算
2.
3.1+true =>2 数学运算
4.'1'+true  =>'1true' 字符串拼接
5.
6.[12]+10  =>'1210' 虽然现在没看见字符串,但是引用类型转换为数字,首先会转换为字符串,所以变为了字符串拼接
7.
8.({})+10 =>'[object Object]10'
9.[]+10  =>'10'
10.
11.{}+10 =>这个和以上说的没有半毛钱关系,因为它根本就不是数字运算,也不是字符串拼接
12.
13.{} 代表一个代码块(块级作用域)
14.+10 才是我们的操作
15.严格写法:
16.{};
17.+10;(+10就相当于0+10)
18.
思考题
1.12+true+false+null+undefined+[]+'珠峰'+null+undefined+[]+true
2.
3.=>'NaN珠峰nullundefinedtrue'
特殊情况:”==”在进行比较的时候,如果左右两边的数据类型不一样,则先转换为相同的类型,再进行比较
对象==对象:不一定相等,因为对象操作的是引用地址,地址不相同,则不相等
1.{name:"xxx"}=={name:"xxx"}
2.[]==[] =>false
3.
4.var obj1={};
5.var obj2=obj1;
6.obj1=obj2 =>true
对象数字:把对象转换为数字,然后再比较 
对象布尔:把对象转换为数字,把布尔也转换为数字 
对象==字符串:把对象转换为字符串
1.[]=='' ->true
2.[12,23]=='12,23' ->true,如果按照下面的规律对象和字符串进行比较的时候转换为数字,两边都为NaN,那么返回的结果应该是false
字符串数字:字符串转换为数字 
字符串布尔:都转换为数字 
布尔==数字:把布尔转换为数字
规律: 
1、不同情况的比较,都是把其它值转换为数字,然后再进行比较的 
2、对象和对象比较的时候,比较的是地址 
3、null==undefined ->true 
4、null = undefined ->false 
5、null、undefined和其它值都不相等 
6、nullnull 
7、undefined==undefined 
8、null=null 
9、undefined=undefined
1.1==true =>true
2.1==false =>false
3.2==true  =>false
4.
5.[]==true:false  都转换为数字  0==1
6.![]==true:false  
7.
8.[]==false: true 都转换为数字 0==0
9.![]==false: true ![]把数组转换为布尔类型再取反  false==false  
关于JS数组常用方法的剖析
数组也是对象数据类型的,也是由键值对组成的
1.var ary = [12,23,34];
2. /*
3. *结构:
4. *  0:12
5. *  1:23
6. *  2:34
7. *  length:3
8. */
9.1.以数字作为索引(属性名),索引从零开始增加
10.2.有一个length属性存储的是数组长度
11.
12.ary[0] 获取第一项
13.ary[ary.length-1] 获取最后一项
数组中每一项的值可以是任何数据类型的
1.//=>多维数组
2.var ary=[
3.    {
4.        name:'xxx',
5.        age:20
6.    }
7.    {
8.        name:'xxx',
9.        age:20
10.    }
11.]
数组的常用方法
按照四个维度记忆:
方法的作用
方法的参数
方法的返回值
原有数组是否改变
push
语法:ary.push()
作用:向数组末尾追加新的内容
参数:追加的内容,可以是一个或多个,可以是各种数据类型
返回值:新增后数组的长度
原有数组改变

pop
语法:ary.pop()
作用:删除数组末尾的最后一项
参数:无
返回值:被删除的那一项内容
原有数组发生改变
 
shift
语法:ary.shift()
语法:删除数组中的第一项
参数:无
返回值:被删除的那一项内容
原有数组发生改变
 
unshift
语法:ary.unshift()
作用:向数组开始位置追加新的内容
参数:追加的内容,可以是一个或多个,可以是各种数据类型
返回值:新增后数组的长度
原有数组改变

splice
删除
语法:ary.splice(n,m)
作用:从索引n开始,删除m个内容
参数:索引 删除项数
返回值:删除的部分用新数组返回
原有数组发生改变

增加
语法:ary.splice(n,0,x)
作用:从索引n开始删除零项(没删除),把x或者更多需要插入的内容放到数组中索引N的”前面”
参数:
返回值:删除的部分用新数组返回
原有数组发生改变

修改
语法:ary.splice(n,m,x)
作用:把原有内容删除掉,然后用新的内容替换这部分信息即可
参数:
返回值:删除的部分用新数组返回
原有数组发生改变

以上所有方法总结 
1、在最前面追加内容的方法
ary.unshift(参数)
ary.splice(0,0,参数)
2、在末尾追加内容的方法
ary.push(参数)
ary.splice(ary.length,0,参数)
ary[ary.length]=参数

3、删除数组中第一项的方法
ary.shift()
ary.splice(0,1)
4、删除数组中最后一项的方法
ary.pop()
ary.splice(ary.length-1)
ary.length–


slice
语法:ary.slice(n,m)
作用:从索引n截取到索引m处(不包含m)
返回值:以新数组存储截取的内容
原有数组不会发生改变

concat
语法:ary.concat()
作用:实现多个数组(或者值)的拼接
参数:数组或者值
返回:拼接后的新数组
原有数组不变

toString
语法:ary.toString()
作用:把数组转换为字符串
参数:无
返回:数组中的每一项用逗号分隔的字符串
原有数组不变

join
语法:ary.join()
作用:和toString类似,也是把数组转换为字符串,但是我们可以设置变为字符串后,每一项之间的连接符
参数:指定的链接符返回
原有数组不变

reverse
语法:ary.reverse() 
作用:把数组倒过来排列
参数:无
返回:排列后的新数组
原有数组改变

sort
语法:ary.sort()
作用:给数组排序
参数:无或者回调函数
返回:排序后的新数组
原有数组改变

不传递参数的情况下:可以给10以内的数字进行升序排列,但是超过10的就无法处理了(多位数只识别第一位,按照第一位的大小进行排列)
升序:ary.sort(function(a,b){return a-b;}) 
降序:ary.sort(function(a,b){return b-a;})

验证数组中是否包含某一项 
indexOf && lastIndex0f
这两个方法不兼容IE6-8
语法:ary.indexof(索引)
作用:获取当前项在数组中第一次或者最后一次出现位置的索引
参数:要检测的值
返回值:获取的当前项的索引
原有数组不变
基于indexOf检测,如果数组中有这一项,返回一个大于等于零的索引 
如果没有这一项,返回的索引为-1

1.//=>验证数组中是否包含某一项
2.
3.if(ary.indexOf(100)>-1){
4.   //=>ARY中包含100这一项
5.}
案例:数组去重 
方案一 indexOf方法
1.Array.prototype.myUnique=function(){
2.    for(let i=0;i<this.length-1;i++){
3.        let item=this[i],
4.            curary=this.slice(i+1);
5.        if(curary.indexOf(item)>-1){
6.            this[i]=this[this.length-1];
7.            this.length--;
8.            i--;
9.        }
10.    }
11.}
12.
方案二 利用对象属性名的唯一性
1.Array.prototype.myUnique=function(){
2.    let obj={};
3.for(var i=0;i<this.length;i++){
4.    if(typeof obj[this[i]]!=='undefined'){
5.        this[i]=this[this.length-1];
6.        this.length--;
7.        i--;
8.        continues;
9.    }
10.        obj[this[i]]=this[i];
11.}
12.obj=null;
13.}
方案三 利用双循环
1.
2.Array.prototype.myUnique=function(){
3.    for(var i=0;i<this.length-1;i++;){
4.    var item=this[i];
5.    for(var j=i+1;j<this.length;j++){
6.        if(item===this[j]){
7.            this[i]=this[this.length-1];
8.            this.length--;
9.            j--;
10.        }
11.    }
12.}
13.}
14.
方案四 排序后相邻去除法
1.Array.prototype.myUnique=function(){
2.    let ary=[];
3.    let _this=[...this];
4.    for(let i=0;i<_this.length;i++){
5.        let item=_this[i],
6.            nextItem=_this[i+1];
7.        if(item!==nextItem[i+1]){
8.            ary.push(item);
9.        }
10.    }
11.    return ary;
12.}
map
语法: ary.map(function(item,index){})
参数:函数
作用: 遍历数组中的每一项,每遍历一次执行一次函数,并把当前项替换成函数执行的返回值,如果函数没有返回值,或者return后面没有值,那么返回的是undefined,统一放在一个新数组中返回
返回值:替换后的新数组
原有数组不变
1.let ary=[12,23,34,25,36,47];
2.let curary=ary.map(function(item,index){
3.    return item+1;
4.});
5.console.log(curary);//=>[13,24,35,26,37,48]
6.console.log(ary);//=>[12,23,34,25,36,47]
7.
8.----------------
9.let ary=[12,23,34,25,36,47];
10.let curary=ary.map(function(item,index){
11.});
12.console.log(curary);//=>[undefined,undefined,undefined,undefined,undefined,undefined]
重写map方法
1.Array.prototype.myMap = function myMap(callback, context) {
2.        var ary = [];
3.        if([].map){
4.            return this.map(callback,context);
5.        }
6.        for(var i=0;i<this.length;i++){
7.            var res = callback.call(context,this[i],i);
8.            ary.push(res);
9.        }
10.        return ary;
11.
12.    }
filter
语法:ary.filter(function(item,index){})
参数:函数
作用:过滤数组,把符合条件的当前项放到新的数组中
返回值:符合条件的新数组
原有数组不变
1.let ary=[12,23,34,25,36,47];
2.let curary=ary.filter((item,index)=>{
3.    return item>20&&item<40;
4.})
5.console.log(curary);//=>[23,34,25,36]
find
语法:ary.find(function(item,index){})
参数:回调函数
作用:过滤数组,把第一次符合条件的当前项返回
返回值:第一次符合条件的那一项
原有数组不变
1.let ary=[1,2,3,4,5];
2.let a=ary.find((item)=>{
3.    return item>1;
4.});
5.console.log(a);//=>2
6.console.log(ary);//=>[1,2,3,4,5]
findIndex
语法:ary.findIndex(function(item,index){})
参数:回调函数
作用:过滤数组,返回第一次符合条件的当前项对应的索引
返回值:第一次符合条件的当前项的索引
原有数组不变
1.let ary=[1,2,3,4,5];
2.let a=ary.find((item)=>{
3.    return item>1;
4.});
5.console.log(a);//=>1
6.console.log(ary);//=>[1,2,3,4,5]
some
语法:ary.some(function(item,index){});
参数:回调函数
作用:数组中有几项,回调函数执行几次,直到回调函数中return结果为true时,停止遍历
返回值:true 或者false,看return后面的值是什么(最终会被转换为布尔类型)
原有数组不变
1.let ary=[1,2,"string",NaN,3,4];
2.let a=ary.some((item)=>{
3.    console.log(item);//=>1,2,string
4.    return typeof item ==="string";
5.});
6.console.log(a);//=>true
7.
8.---------------
9.let ary=[1,2,"string",NaN,3,4];
10.let a=ary.some((item)=>{
11.    console.log(item);//=>1,2,string,NaN,3,4
12.    return 0;
13.});
14.console.log(a);//=>false,因为Boolean(0)=>false
every
语法:ary.every((item,index)=>{});
参数:回调函数
作用:遍历数组中的每一项,每遍历一次,就执行一次回调函数,只要遇到回调函数返回值的结果为false立马停止遍历
返回值:true 或者false
原有数组不变
1.let ary=[1,2,"string",NaN,3,4];
2.let a=ary.every((item)=>{
3.    console.log(item);//=>1,2,string,NaN,3,4
4.    return item==="number";
5.});
6.console.log(a);//=>true
7.------------
8.let ary=[1,2,"string",NaN,3,4];
9.let a=ary.every((item)=>{
10.    console.log(item);//=>1,2,string
11.    return item==="number";
12.});
13.console.log(a);//=>true
reduce
语法:ary.reduce((prev,item)=>{},init);
参数:回调函数(第一个参数是前一次回调函数的返回结构,第二项是当前项),init代表了传递给函数的初始值
作用:作为累加器,数组中的每个值(从左到右开始缩减),最终计算为一个值
返回值:最终得到的结果
原有数组不变
1.let ary=[1,1,1,1,1,,1,1,1,1,1];
2.let a=ary.reduce((prev,item)=>{
3.    console.log(prev, item);
4.    return prev-item;
5.},10);
6.console.log(a);//=>0,遇到空位直接跳过
7.console.log(ary);//=>[1,1,1,1,1,,1,1,1,1,1];
reduceRight
语法:ary.reduceRight((prev,item)=>{},init)
参数:回调函数(第一个参数是前一次回调函数的返回结构,第二项是当前项),init代表了传递给函数的初始值
作用:作为累加器,数组中的每个值(从右到左开始缩减),最终计算为一个值
返回值:最终得到的结果
原有数组不变
1.let ary=[-1,1,-1,1];
2.let b=ary.reduceRight((prev,item)=>{
3.    console.log(prev, item);
4.    return prev*item;//=>10*1*-1*1*-1
5.},10);
6.console.log(b);//=>10
JS中关于字符串的一些细节知识
在JS中所有用单引号或者双引号包起来的都是字符串,每一个字符串是由零到多个字符组成
1.var str = 'zhufengpeixun';
2.str.length ->字符串长度
3.str[0] ->'z'
4.str[str.length-1] ->'n'
5.str[100] ->undefined
6.
7.//=>字符串中的每一个字符,都有一个自己对应的索引,也有类似于数组一样的length代表自己的长度
8.
9.//=>循环遍历字符串,输出每一项字符
10.for(var i=0;i<str.length;i++){
11.    console.log(str[i]);
12.}
字符串的常用方法
字符串是基本数据类型,字符串的每一次操作都是值直接的进行操作,不像数组一样是基于空间地址来操作的,所以不存在原有字符串是否改变这一说,肯定都是不变的
charAt && charCodeAt
语法:str.charAt(索引)
作用:charAt根据索引获取指定位置的字符,charCodeAt不仅仅获取字符,它获取的是字符对应的Unicode编码值(ASCII)
参数:索引
返回值:字符或者对应的编码


indexOf && lastIndexOf
基于这两个方法,可以获取字符在字符串中第一次或者最后一次出现位置的索引,有这个字符,返回大于等于零的索引,不包含这个字符,返回的结果是-1,所以可以基于这两个方法,验证当前字符串中是否包含某个字符

1.var str = 'zhufengpeixun';
2.if(str.indexof('@')>-1){
3.    //=>条件成立说明包含@符号
4.}
slice
语法:str.slice(n,m)
作用:str.slice(n,m)从索引n开始找到索引为m处(不包含m),把找到的字符当做新字符串返回
返回值:截取的字符串

substring
语法:str.substring(n,m)
作用:str.substring(n,m)从索引n开始找到索引为m处(不包含m),把找到的字符当做新字符串返回,不支持负数作为索引
返回值:截取的字符串

substr
语法:str.substr(n,m)
作用:从索引n开始截取m个字符

toUpperCase && toLowerCase
语法:str.toUpperCase()/str.toLowerCase()
作用:实现字母的大小写转换 
toUpperCase 小写转化为大写
toLowerCase 大写转换为小写
参数:无

split 
和数组中的join相对应,数组中的join是把数组每一项按照指定的连接符变为字符串,而split是把字符串按照指定的分隔符,拆分成数组中每一项

replace
语法:str.replace(原有字符,要替换的新字符)
作用:替换字符串中的原有字符
返回:替换后的字符串

真实项目中的需求
1.时间字符串格式化
需求:有一个时间字符串”2018-4-4 16:26:8”.我们想基于这个字符串获取到”04月04日 16时26分”
1.var str="2018-4-4 16:26:8",
2.    ary=str.split(' '),
3.    aryLeft=ary[0],
4.    aryRight=ary[1];
5.    month=aryLeft.split('-')[1],
6.    day=aryLeft.split('-')[2],
7.    hour=aryRight.split(':')[0],
8.    minute=aryRight.split(':')[1];
9.
10.function fn(n){
11.    return n<10?"0"+n:n;
12.}
13.var date=fn(month)+'月'+fn(day)+'日 '+fn(hour)+'时'+fn(minute)+'分'
14.
15.console.log(date);
16.
17.--------------正则
18.let reg=/^(\d{4})[-/](0?[1-9]|1[0-2])[-/](0?[1-9]|[12]\d|3[01])\s+(0?[1-9]|1\d|2[0-3]):(0?\d|[1-5]\d):(0[1-9]|[1-5]\d)$/;
19.console.log(reg.exec(str));
2.URL地址问号传参解析
有一个URL地址”http://www.zhufengpeixun.cn/stu/?1x=1&name=AA&sex=man#teacher“地址问号后面的内容是我们需要解析出来的参数信息 
{ 
1x:1, 
name:’AA’, 
sex:’man’ 
}
1.var str="http://www.zhufengpeixun.cn/stu/?1x=1&name=AA&sex=man#teacher";
2.var indexASK=str.indexOf("?");
3.var indexWell=str.indexOf('#');
4.
5.if(indexWell>-1){
6.    str=str.substring(indexASK+1,indexWell);
7.}else{
8.    str=str.substr(indexASK+1);
9.}
10.var ary=str.split('&');
11.var obj={};
12.for(var i=0;i<ary.length;i++){
13.    var curary=ary[i].split('=');
14.    obj[curary[0]]=curary[1];
15.}
16.
案例:获取URL问号后传参值--函数封装
1.function queryParameter(URL){
2.    var indexASK=URL.indexOf("?"),
3.        indexWell=URL.indexOf('#');
4.    indexWell>-1?URL=URL.substring(indexASK+1,indexWell):URL=URL.substring(indexASk+1);
5.    var ary=URL.split('&'),
6.        obj={};
7.    for(var i=0;i<ary.length;i++){
8.        var item=ary[i],
9.            curary=item.split("=");
10.            obj[curary[0]]=curary[1];
11.    }
12.    return obj;
13.}
JS中的数学函数
Math称为数学函数,但是属于对象类型的
1.typeof Math//=>'object'
之所以叫做数学函数,是因为Math这个对象中提供了很多操作数字的方法
Math中提供的常用方法
abs
语法:Math.abs()
作用:取绝对值

ceil && floor
语法:Math.ceil()
作用:

round
语法:Math.round()
作用:四舍五入

sqrt 
语法:Math.sqrt()
作用:开平方

pow
语法:Math.pow(n,m)
作用:n的m次方

max && min
语法:Math.max()
作用:获取最大值或最小值
PI
语法:Math.PI()
作用:获取圆周率

random
语法:Math.random()
作用:获取[0,1)的随机小数
获取[n,m]之间的随机整数 
Math.round(Math.random()*(m-n)+n)
 
获取四位随机验证码--封装函数
1.function queryCode(str){
2.    var result="";
3.    while(result.length<4){
4.        var mathIndex=Math.round(Math.random()*(str.length-1));
5.        result.indexOf(str.charAt(mathIndex))===-1?result+=str.charAt(mathIndex):null;
6.    }
7.    return result;
8.}
9.queryCode();
函数
1.function fn(n,m){//=>形参:入口
2.    //=>函数体
3.    var total = 0;
4.    total=n+m;
5.    console.log(total)
6.}
7.fn(10,20);//=>实参:给形参传递的具体值
8./
9.* var a =12;
10.* fn(a,1===1?10:0);//=>实参一定是值,即使我们写的是变量或者表达式,也是把变量或者表达式计算的结果作为值传递给形参变量
11.*/
函数执行的时候,都会形成一个全新的私有作用域(私有的栈内存),目的是:
1.把原有堆内存中存储的字符串变为JS表达式执行
2.保护里面的私有变量不受外界的干扰(和外界是隔离的) 
我们把函数执行的这种保护机制,称之为“闭包”

1.function fn(n,m){
2.    var total=0; //=>total:私有变量
3.    total=n+m;
4.}
5.fn(10,20);
6.console.log(total);//=>Uncaught ReferenceError: total is not defined TOTAL是私有变量,我们无法在函数的外面直接获取这个值(闭包)
函数中的return
函数的入口:形参 
函数的出口:返回值 return
把函数运行的结果(或者函数体中的部分信息)拿到函数外面去使用
1.function fn(n,m){
2.    var total = 0;
3.    total = n+m;
4.    return total;//=>并不是把total变量返回,返回的是变量存储的值,return返回的永远是一个值
5.}
6.fn //=>代表的是函数本身(函数本身也是个值,本身代表的是堆内存中的代码字符串)
7.fn(10,20);//=>代表的是函数执行(不仅如此,它代表的是函数执行后,返回的结果[return返回的值])
1.function fn(n,m){
2.    var total = 0;
3.    total = n+m;
4.}
5.var res = fn(10,20);//=>如果当前函数没有return结果出来(或者return;啥也没返回),函数执行在外面拿到的结果都是 undefined
1.function fn(n,m){
2.    //=>如果n/m有一个没有传递值,我们返回零
3.    if(n===undefined || m=undefined){
4.        return 0;//=>return还有一个作用:类似于循环中的break,能够强制结果函数体中代码的执行(return后面的代码不在执行)
5.}
6.    var total=0;
7.    total=n+m;
8.    return total;
9.}
10.fn(10);//=>此时n=10,m为undefined,相当于10+undefined,Number(undefined)=>NaN,10+NaN=>NaN
11.
12.
13.
14.===小知识点1===
15.1、n===undefined 经常这样判断n的值是否为undefined,这种方式可以
16.2、n==undefined 这种模式不好,因为null==undefined也是相等的(===比较才不相等)
17.3、typeof n=='undefined' 真实项目中开发者更喜欢这种判断模式
18.
19.
20.
21.===小知识点2===
22.1、total=0; 0是有值的,值时0,从内存方面来说,会在栈内存中占一个位置
23.2、total=null; 开发者更喜欢用null来作为初始值,null是空对象指针,是不占内存的;
24.
函数中的arguments
形参是有局限性的:我们需要具体的知道用户和执行的时候传递实参数量、顺序等,才可以使用形参变量定义对应的入口
arguments:函数内置的实参集合(内置:函数天生就存在的机制,不管你是否设置了形参,也不管你是否传递了实参,arguments都有,始终存在的) 
1.function sum(){
2.    console.log(arguments);
3.}
4.
argument是一个类数组,不是数组,不能直接使用数组中的方法

即使设置形参变量,形参该是什么值还是什么值,但是arguments使用存储的是所有传递进来的实参,所以它被称为实参集合

1.function sum(){
2.    console.log(arguments.callee===sum);//=>true
3.}

案例:任意数求和
1.//=>思路:先将实参中的每一项都转换为数字类型,如果是有效数字则累加,否则,不累加
2.
3.function sum(){
4.    var total=null;
5.    for(var i=0;i<arguments.length;i++){
6.        var item=arguments[i];
7.        if(!isNaN(Number(item))){
8.            total+=Number(item);
9.}
10.}
11.return total;
12.}
实名函数和匿名函数
实名函数:有函数名的
匿名函数:没有函数名的 
函数表达式:把函数当做值赋值给变量或者元素的事件
自执行函数:创建和执行一起完成的,自执行函数正常写法是”(function(){…})();”但是,JS中会将以”function“ 开头的语句认定为函数声明语句,而自执行函数得到的是一个值,所以不可以直接这样写。所以要以运算符或者括号开头~func…或者以变量接收var a=function(){…}();
1.===函数表达式===
2.
3.var fn=function (){
4.
5.}
6.
7.oBox.onclick=function (){
8.
9.}
10.
11.
12.===自执行函数
13.(function (){})();
14.
15.//=>因为自执行函数不能以function做开头,所以function前加上运算符。
16.
17.~function(){
18.        console.log(this)    //=>Window
19.    }();
20.    //return 值为~undefined=>-1
21.    //二进制否运算符(~)将每个二进制位都变为相反值(0变为1,1变为0)。
22.
23.!function(){
24.        console.log(this)    //=>Window
25.    }();
26.    //return 值为!undefined=>true
27.
28.-function(){
29.        console.log(this)    //=>Window
30.    }();
31.    //return 值为-undefined=>NaN
32.
33.+function(){
34.            console.log(this)    //=>Window
35.    }();
36.    //return 值为+undefined=>NaN
37.
38.
DOM
DOM树
dom tree 
当浏览器加载HTML页面的时候,首先就是DOM结构的计算,计算出来的DOM结构就是DOM树(把页面中的HTML标签像树状结构一样,分析出之间的层级关系)

DOM树描述了标签和标签之间的关系(节点间的关系),我们只要知道任何一个标签,都可以依据DOM中提供的属性和方法,获取到页面中任意一个标签或者节点
获取DOM元素的方法
getElementById
通过元素的ID获取指定的元素对象,使用的时候都是document.getELementById("")此处的document是限定了获取元素的范围,我们把它称之为”上下文(context)”
1、getElementById的上下文只能是document 
因为严格意义上一个页面的id是不能重复的,浏览器规定在整个文档中既可以获取这个唯一的ID
2、 如果页面中的ID重复了,我们基于这个方法只能获取到第一个元素,后面相同ID元素无法获取
3、在IE6-7浏览器中,会把表单元素(input)的name属性值当做ID来使用(建议:以后使用表单元素的时候,不要让name和id的值有冲突)
getElementsByTagName
[context].getElementsByTagName在指定的上下文中,根据标签名获取到一组元素集合(HTMLCollection)
1、 获取的元素集合是一个类数组(不能直接使用数组的方法) 
2、它会把当前上下文中,子子孙孙(后代)层级内的标签都获取到(获取的不仅仅是儿子级的) 
3、基于这个方法获得的结果永远都是一个集合(不管里面是否有内容,也不管有几项,它是一个容器或者集合),如果想操作集合中具体的某一项,需要基于索引获取到才可以
 
案例:寻找所有id为HAHA的元素
思路:先获得id为box的div下的所有元素,得到一个类数组,创建一个新数组,再遍历类数组中的每一项,如果id等于HAHA则存储到数组中
第一种方案
1.<div class="box" id="box">
2.    <ul>
3.        <li class="item1 item2">新闻</li>
4.        <li class="item1">电影</li>
5.        <li class="item2">音乐</li>
6.    </ul>
7.    <div id="HAHA" name="hobby">最新新闻</div>
8.    <div>最新电影</div>
9.    <div id="HAHA">最新音乐</div>
10.</div>
11.
12.var oBox=document.getElementById('box'),
13.    nodeList=oBox.getElementsByTagName('*'),
14.    ary=[];
15.function queryAllById(id){
16.    for(var i=0;i<nodeList;i++){
17.        var item=nodeList[i];
18.        item.id===HAHA?ary.push(item):null;
19.    }
20.    return ary;
21.}
第二种方案
1.console.log(HAHA);
2.//=>HAHA为id名
在JS中,默认会把元素的ID设置为变量(不需要再获取设置),而且ID重复,获取的结果就是一个集合,包含所有ID项,不重复就是一个元素对象(类似于ById获取的结果)
getELementsByClassName
[context].getELementsByClassName()在指定的上下文中,基于元素的样式类名(class=”xxx”)获取到一组元素集合
1、真实项目中,我们经常是基于样式类来给元素设置样式,所以在JS中,我们也会经常基于样式类来获取元素,但是此方法在IE6-8下不兼容
兼容处理方案
1.Node.prototype.queryElementsByClassName = function queryElementsByClassName() {
2.    if (arguments.length === 0) return [];
3.    var strClass = arguments[0],
4.        nodeList = utils.toArray(this.getElementsByTagName('*'));
5.    strClass = strClass.replace(/^ +| +$/g, '').split(/ +/);
6.    for (var i = 0; i < strClass.length; i++) {
7.        var reg = new RegExp('(^| +)' + strClass[i] + '( +|$)');
8.        for (var k = 0; k < nodeList.length; k++) {
9.            if (!reg.test(nodeList[k].className)) {
10.                nodeList.splice(k, 1);
11.                k--;
12.            }
13.        }
14.    }
15.    return nodeList;
16.};
getElementsByName
document.getElementsByName()它的上下文也只能是document,在整个文档中,基于元素的name属性值获取一组节点集合(也是一个类数组)
1、在IE9及以下版本浏览器当中,只对表单元素的name属性起作用(正常来说,我们项目中只会给表单元素设置name,给非表单元素设置name,其实是一个不太符合规范的操作)

querySelector
[context].querySelector()在指定的上下文中基于选择器(类似于CSS选择器)获取到指定的元素对象(获取到的是一个元素,哪怕选择器匹配了多个,我们只获取第一个)
querySelectorAll
在querySelector的基础上,我们获取到选择器匹配到的所有元素,结果是一个节点集合(NodeList)

querySelector/querySelectorAll都是不兼容IE6-8浏览器的,不考虑兼容的情况下,我们能用byid或者其它方式获取的,也尽量不要用这两个方法,这两个方法性能消耗较大
1.<div id="div1" class="fon mark" name="div1">01</div>
2.<div id="div2" class="mark">02</div>
3.<div id="div1" class="fon">03</div>
4.
5.<script>
6.    console.log(document.querySelectorAll("#div1"));/*ID选择器*/
7.    console.log(document.querySelectorAll('.mark'));/*类选择器*/
8.    console.log(document.querySelectorAll('body>div'));/*子级选择器*/
9.    console.log(document.querySelectorAll('div'));/*标签选择器*/
10.    console.log(document.querySelectorAll("body div"));/*后代选择器*/
11.    console.log(document.querySelectorAll("div[name='div1']"));/*标签属性选择器*/
12.    console.log(document.querySelectorAll("*"));/*通配符选择器*/
13.</script>
document.head
获取head元素对象 
直接调取document这个实例上的head属性
document.body
获取body元素对象 
直接调取document这个实例上的body属性
document.documentElement
获取HTML元素对象 
直接调取document这个实例上的documentElement属性
1.//=>需求:获取浏览器一屏幕的宽度和高度(兼容所有的浏览器)
2.
3.document.documentELement.clientWidth ||
4.document.body.clientWidth
5.
6.document.documentELment.clien
7.tHeight ||
8.document.body.clientHeight
节点(node)
在一个HTML文档中出现的所有东西都是节点
元素节点(HTML标签)
文本节点(文字内容、空格、换行)
注释节点(注释内容)
文档节点(document)
…
每一种类型的节点都会有一些属性区分自己的特性和特征
nodeType:节点类型
nodeName:节点名称
nodeValue:节点值
元素节点
nodeType:1
nodeName:大写标签名
nodeValue:null
文本节点
nodeType:3
nodeName:”#text”
nodeValue:文本内容
注释节点
nodeType:8
nodeName:”#comment”
nodeValue:注释内容
文档节点
nodeType:9
nodeName:”#document”
nodeValue:null
描述节点之间关系的属性
parentNode
获取当前节点唯一的父亲节点
childNodes
获取当前节点的所有子节点
子节点:只获得儿子级别的
所有:包含元素节点、文本节点等
children
获取当前节点所有的元素子节点 
在IE6-8中会把注释节点也当做元素节点获取到,所以兼容性不好
firstChild
获取当前节点的第一个子节点(可能是元素或者文本)
firsrElementChild
获取当前节点的第一个元素子节点 
在IE6-8中不兼容
lastChild
获取当前节点的最后一个子节点(可能是元素或者文本)
lastElementChild
获取当前节点的最后一个元素子节点 
在IE6-8中不兼容
previousSibling
获取当前节点的上一个哥哥节点(获取的哥哥可能是元素也可能是文本等)
previousElementSibling
获取上一个哥哥元素节点(不兼容IE6-8)
nextSibling
获取当前节点的下一个弟弟节点(获取的哥哥可能是元素也可能是文本等)
nextElemnentSibling
获取下一个弟弟元素节点(不兼容IE6-8)
兼容处理1--获取当前元素的所有元素子节点
基于children不兼容IE低版本浏览器(会把注释当做元素节点)
1.//=>思路:首先获取当前元素下所有的子节点,然后遍历这些节点,筛选出元素的(nodeType===1),把筛选出来的结果单独存储起来即可
2.
3./
4.*children:get all the element nodes of the current element
5.*@parameter
6.*   curEle:[object] current element
7.*@return
8.*   [Array] all the element nodes
9.*by team on 2018/04/07 12:36    
10.*/
11.function children(curEle){
12.    var childEle=curEle.childNodes;
13.    var aryEle=[];
14.    for(var i=0;i<childEle.length;i++){
15.        var item=childEle[i];
16.        if(item.nodeType===1){
17.            aryEle.push(item);
18.        }
19.    }
20.    return aryEle;
21.}
22.
兼容处理2--获取当前元素的上一个哥哥元素节点
基于previousElementSibling不兼容IE低版本浏览器
1.//=>先找当前元素的哥哥节点,看是否为元素节点,不是的话,基于哥哥,找哥哥的上一个哥哥节点...一直到找到元素节点或者已经没有哥哥了(说明我就是老大)则结束查找
2./
3.*prev:get the last elder brother element node of the current element
4.*@parameter
5.*   curEle:[object] current element
6.*@return
7.*   [object] last elder brother element
8.*by team on 2018/04/07 12:48    
9.*/
10.function prev(curEle){
11.   var item=curEle.previousSibling;
12.       while(item && item.nodeType!==1){//=>item是为了验证当前这个元素是否还设有,如果没有item会为null,Boolean(item)=>false
13.           item=item.previousSibling;
14.       }
15.       return item;
16.}
兼容处理3---获得当前项下一个弟弟元素节点
思路:先找到当前项的弟弟节点,判断该弟弟节点的nodeType===1,如果不等于就继续往前找 一直找到末尾
1./
2.* next:get the next element of the current element
3.* @parameter:[object] the current element
4.* return:the next element
5.* by Fay on 17:58
6./
7.function next(curEle){
8.    var item=curEle.nextSibling;
9.    while(item && item.nodeType!==1){
10.        item=item.nextSibling;
11.    }
12.    return item;
13.}
兼容处理4--获取当前项所有的弟弟元素节点
思路:先获取当前元素的弟弟节点,创建一个空数组,如果当前元素的弟弟节点的nodeType===1则存起来,一直往下找找到末尾
1./
2.* nextAll:get all of the next elements by the current element
3.* @parameter:[object] the current element
4.* return: all of the next elements
5.* by Fay on 18:06
6.*/
7.function nexAll(curEle){
8.    var item=curEle.nextSibling,
9.        ary=[];
10.    while(item){
11.        item.nodeType===1?ary.push(item):null;
12.        item=item.nextSibling;
13.    }
14.    return ary;
15.}
兼容处理5--获取当前项所有的哥哥元素节点
1./
2.* preAll:get all of the previous elements by the current element;
3.* @parameter:[object] the current element
4.* return:[object] all of the previous elements
5.* by Fay on 18:11
6.*/
7.function preAll(curEle){
8.    var item=curEle.previousSibling,
9.        ary=[];
10.    while(item){
11.        item.nodeType===1?ary.push(item):null;
12.        item=item.previousSibling;
13.    }
14.    return ary;
15.}
兼容处理6--获得当前项的所有兄弟元素节点
思路:将所有的哥哥元素节点与所有的弟弟元素节点相加
1./
2.* siblings:get all siblings elements by the current element
3.* @parameter:[object] the current element
4.* return:all siblings elements
5.* by Fay on 18:25
6.*/
7.function siblings(curEle){
8.    var preItem=curEle.previousSibling,
9.        nextItem=curEle.nextSibling,
10.        ary=[];
11.    while(preItem){
12.        preItem.nodeType===1?ary.push(preItem):null;
13.        preItem=preItem.previousSibling;
14.    }
15.    while(nextItem){
16.        nextItem.nodeType===1?ary.push(nextItem):null;
17.        nextItem=nextItem.nextSibling;
18.    }
19.    return ary;
20.}
兼容处理7--获得当前项的索引
思路:当前元素有多少个哥哥节点,索引就是多少,即获取当前项哥哥节点的个数
1./
2.* index:get the index of the current element
3.* @parameter:[object] the current element
4.* return:[number] the index of the current element
5.* by Fay on 18:17
6.*/
7.function index(curEle){
8.    var item=curEle.previousSibling,
9.        ary=[];
10.    while(item){
11.        ary.push(item);
12.        item=item.previousSibling;
13.    }
14.    return ary.length;
15.}
关于DOM的增删改
createElement
创建一个元素标签(元素对象) 
document.createELement([标签名]) 
Document类原型上的属性,属性值是函数
案例:通过动态创建元素快速获取queryURLParameter
a元素有一些内置属性:
hash:存储了哈希值 ‘#teacher’
search:问号传递参数值,没有传递是空字符串 ‘?name=zxt&age=27&sex=0’ 
hostname:域名 ‘www.zhufengpeixun.cn’
pathname:路径 ‘/stu/’
1.function queryURLParameter(url){
2.var link=document.createElement('a');
3.link.href=url;
4.var search=link.search;
5.if(search.length===0) return;
6.   url=search.substr(1);
7.   var ary=url.split('&'),
8.    obj={};
9.for(var i=0;i<ary.length;i++){
10.    var curary=ary[i].split('=');
11.    obj[curary[0]]=curary[1];
12.}
13.    link=null
14.    return obj;
15.}
appendChild
把一个元素对象插入到指定容器的末尾
[container].appendChild([newELe])
Node类原型上的属性,属性值是函数
1.var newP = document.createElement('p');
2.document.body.appendChild(newP);
3.newP.innerHTML = '我是P!!';
4.newP.style.backgroundColor = 'red';
insertBefore
把一个元素对象插入到指定容器中某一个元素标签之前
[container].insertBefore([newEle],[oldEle])
Node类原型上的属性,属性值是函数
1.<div id="box2" class="box">2</div>
2.//=>创建
3.    var oDiv = document.createElement('div');
4.     oDiv.id='div1';
5.    oDiv.className='box';
6.    oDiv.innerText='1';
7.
8.document.body.insertBefore(oDiv,document.getElementById('box2'));
9.
10.//也可以这样写,直接用id名
11.
12.document.body.insertBefore(oDiv,box2);
cloneNode
把某一个节点进行克隆 
[curELe].cloneNode():浅克隆,只克隆当前的标签 
[curELe].cloneNode(true):深克隆,当前标签及其里面的内容都一起克隆了
Node类原型上的属性,属性值是函数
1.<div class="box" id="box1">1</div>
2.<div class="box" id="box2">2</div>
3.
4.<script>
5.    var box1=document.getElementById('box1'),
6.        box2=document.getElementById('box2');
7.    var box3=box2.cloneNode();
8.    document.body.appendChild(box3);
9.    var box4=box2.cloneNode(true);
10.    document.body.appendChild(box4);
11.</script>

removeChild
在指定容器中删除某一个元素 
[container].removeChild([curEle]) 
Node类原型上的属性,属性值是函数
set/get/removeAttribute
设置/获取/删除 当前元素的某一个自定义属性 
设置的自定义属性值最终都会以字符串的形式展现 
[container].setAttribute([key],[value]) 
Element类原型上的属性,属性值是函数
使用xxx.index=0和xxx.setAttribute(‘index’,0)这两种设置自定义属性的区别?
xxx.index:是把当前操作的元素当做一个普通对象,为其设置一个属性名(和页面中的HTML标签没关系)


xxx.setAttribute:把元素当做特殊的元素对象来处理,设置的自定义属性和页面结构中的DOM元素映射在一起的



使用DOM方法设置的自定义属性与对象设置自定义属性无法互相获取,两种方法是独立的
第一种是基于对象键值对操作方式,修改当前元素对象的堆内存空间来完成
第二种是直接修改页面中的HTML标签的结构来完成(此种方法设置的自定义属性可以在结构上呈现出来)

复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值