JavaScript第二周总结

110 阅读16分钟

一、数组的基础

1.1、创建数组:

1、直接量方式:var arr=[值1,......];

2、构造函数:var arr=new Array(值1,......);

构造函数创建数组有一个:new Array(num);这句话的意思是:创建了一个长度为num的空数组,里面没有任何东西,只有无数的undefined

1.2、按值传递:(面试题)

题目:var a=x; var b=a; 修改a,b变不变,或者修改b,a变不变

分两种情况讨论:

1、传递的如果是原始类型:

其实是复制了一个副本给对方,两者互不影响

2、传递的如果是引用类型(js中除了原始类型就是引用类型(函数、数组))--浅拷贝

因为引用类型很大,比原始类型大很多,不可能保存变量在本地,而是保存了一个地址值而已,其实是赋值了自己的地址值给对方,两者用的是同一个地址,一个发生变化,另一个也会改变。

1.3、如何释放一个引用类型:

一定要看清有几个变量引用着这个类型,每个变量都释放后,才能释放干净

在js底层有一个垃圾回收器,只有垃圾回收器的计数器(记录着这个数据有几个人使用)为0的时候,才会删除不要的数据

建议:我们的代码都要封装为一个函数,函数的一切变量都会自动释放

索引数组:下标都是数字组成的数组

二、hash数组:

又称关联数组,下标是可以自定义的

由来:索引数组的下标无具体意义,不便于查找

2.1、创建:(2步)

1、创建空数组:var arr=[];

2、为数组添加自定义下标并且赋值: arr["自定义下标"]=新值;

2.2、访问元素:

arr["自定义下标"];

2.3、遍历hash数组

hash数组的length失效了,length永远为0

遍历hash数组不能再使用for循环,必须使用for in循环(专门遍历hash数组的)

  for(var i in 数组名){
      i;//下标
      数组名[i];//当前次元素
  }

不止能遍历hash数组还能遍历索引数组

建议:索引数组依然使用for循环,hash数组使用for in循环

2.4、hash数组的原理

hash算法: 将字符串,计算出一个尽量不重复的数字(地址值),字符串的内容相同,则计算出的数字相同

添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将你要保存的数据放到此地址保存起来

获取元素:将指定的自定义下标交给hash算法,得到一个和当初保存的的一样的数字(地址值),通过此地址找到你当初保存的数据,取出来使用

2.5、一切对象的底层都是hash数组

js里面一切东西都是对象,万物皆对象,除了undefined和null

三、数组的API

3.1、数组转字符串

var str=arr.join("自定义连接符");

固定套路:

1、鄙视题:将数组里面的内容拼接为一句话/单词--无缝拼接,拼接了一个空字符串

var arr=["h","e","l","l","o"," ","w","o","r","l","d"];
var str=arr.join("");
console.log(str);//结果:hello World

2、将数组拼接为DOM页面元素--数据渲染页面

//HTML中的内容
<select></select>
//js中的内容
var sel=document.getElementsByTagName("select")[0];
var arr=["-请选择-","北京","南京","重庆","湖南","天津","上海"];//读取数据,一般不会是自己创建
var str="<option>"+arr.join(</option><option>)+"</option>";//option可以换成任何其他标签
sel.innerHTML=str;//innerHTML能识别标签

3.2、数组的拼接

添加元素的新方式, 将你传入的实参全部拼接到arr的末尾:

var newArr=arr.concat(新值1,arr1,......);//传入的数组元素会被打散为单个元素

特殊:1、不修改原数组,只会返回一个新数组。 2、concat支持传入数组参数,悄悄的将你传入的数组打散为单个元素再拼接

3.3、截取子数组

根据你传入的开始下标截取到结束下标:var subArr=arr.slice(starti,endi+1);

特殊:1、不修改原数组,只会返回一个新数组 2、左闭右开 3、endi可以省略不写,会从开始位置一直截取到末尾 4、starti也可以省略,如果两个实参都省略,会从头截到尾的完全复制一份---深拷贝-复制了一个副本给对方5、支持负数参数,-1代表倒数第一个

下面的API会修改原数组

3.4、删除、插入、替换

删除:var dels=arr.splice(starti,n);//n代表删除的个数 虽然修改原数据,但也有返回值,返回的是被删除的数据

插入:arr.splice(starti,0,新值,...);//在某位置前面插入新值特殊:1、原starti位置的元素以及后续元素都会向后移动。2、尽量不要插入一个数组,会导致我们的数组一些是一维,一些是二维,遍历的时候不方便

替换:var dels=arr.splice(starti,n,新值,.....);//删除的个数不必与插入的个数相同

3.5、翻转数组

arr.reverse();//不常用

3.6、数组的排序

1、鄙视题:冒泡排序:将数据按照从小到大进行排序

var arr=[32,4,23,5546,2253,67,47,0,43,1];
for(var i=1;i<arr.length;i++){
    for(var j=0;j<arr.length-i;j++){
        if(arr[j]>arr[j+1]){
            var m=arr[j];
            arr[j]=arr[j+1];
            arr[j+1]=m;
        }
    }
}
console.log(arr);

2、正式开发:arr.sort();

默认:将数组中的元素转为字符串后,再按位PK每个字符的Unicode(ASCII码)

  1. 升序排列(从小到大)
arr.sort(function(a,b){
   console.log(a);//后一个数字
   console.log(b);//前一个数字
   return a-b;
})
  1. 降序排列(从大到小)
arr.sort(function(a,b){
   return b-a;
})

切记:1、网页上有功能带有排序,那么底层一定是数组,因为js中只有数组可以排序。2、网页上有随机的功能,底层一定是用了随机数公式

3.7、栈和队列

栈:数组只能从某一端(开头/结尾)进出;

  • 开头进:arr.unshift(新值,...);//向前添加,后面的元素的下标会发生变化

  • 开头出:var first=arr.shift();//一次只能 删除一个,其他元素的下标发生改变

  • 结尾进:arr.push(新值,...);//向后添加元素

  • 结尾出:var last=arr.pop();//从末尾删除

队列:一段进,另一端出:

  • 开头进:arr.unshiift(新值,...);

  • 结尾出:var last=arr.pop();

  • 结尾进:arr.push(新值,...);

  • 开头出:var fisrt=arr.unshift();

上面都是ES3提供的API,下面是ES5提供的6个API

3.8、判断(2个)

every:每一个,要求所有元素都满足条件才会为true,类似于&&

var bool=arr.every(function(val,i,arr){
    //val-当前的值(不能省略)
    //i-当前值的下标
    //arr-当前数组本身
    return 判断条件;
})

some:有一些,要求只要有一个元素满足条件就会为true,类似于||

var bool=arr.some(function(val,i,arr){
    return 判断条件;
})

3.9、遍历

遍历目的:拿到数组中的每个元素做相同或者相似的操作

forEach--直接修改原数组

arr.forEach(function(val,i,arr){
    你的操作;
})

map--不修改原数组,返回一个新数组

var newArr=arr.map(function(val,i,arr){
    return 操作;
})

3.10、过滤和汇总

过滤:筛选出你需要的部分,不修改原数据

var subArr=arr.filter(function(val,i,arr){
    return 判断条件;
})

汇总:不修改原数据

var result=arr.reduce(function(prev,val,i,arr){
    return prev+val;//数组求和,加号可以换成任何其他算术符
},基础值)

ES6箭头函数:简化一切匿名函数: 把function去掉,()与{}之间添加=>,如果()里面只有一个参数,那么()可以去掉,如果{}里面只有一句话,那么可以省略{}

例如:arr.forEach(val=>val+1); var result=arr.reduce((prev,val)=>prev+val);

四、二维数组

4.1、创建:

var arr=[    ['张三',18,900],
    ['李四',29,800],
    ['老王',30,600]
];

4.2、访问:

arr[行下标][列下标];

特殊:1、列下标越界,返回undefined。2、行下标越界,会报错,因为行下标越界已经得到undefined,undefined不能做任何操作,所以报错。

4.3、遍历:

必须是两层循环,外层循环控制行,内层循环控制列

for(var r=0;r<arr.length;r++){
    for(var c=0;c<arr[r].length;c++){
        console.log(arr[r][c]);
    }
}

五、字符串

多个字符组成的只读字符数组,不能直接原字符串,返回一个新字符串

与数组的相同点:

  1. 字符串中长度:str.length;
  2. 获取字符串中的某个字符:str[i];
  3. 遍历字符串
  4. 所有数组不修改原数组的API,字符串也可以使用,比如(concat、slice)

与数组的不同点:

所有数组可以直接修改原数组的API,字符串都不可以使用,比如排序等

引用/对象类型:11个

  • String Number Boolean -->包装类型
  • Array Function Date Math RegExp(正则:验证)
  • Error(错误) Object(面向对象开发方式)
  • Global(全局对象)--只有在浏览器中被window对象代替了,保存着全局变量和全局函数,只不过window可以省略不写,后面在学习node.js这个后端语言的时候,全局对象叫Global

包装类型:专门用于将原始类型的值封装为一个引用类型的对象

  • 原因:原始类型的值原本就是没有任何属性和方法,意味着原始类型是本来是不支持做任何操作的
  • 使用:只要你使用原始类型的变量调用属性或者方法,就会自动包装
  • 释放:方法的调用完毕后,自动释放包装类型,变为原始类型
  • 为什么null和undefined不能使用,因为前辈们没有给他们提供包装类型

5.1、字符串的API:

1、转义字符:\

作用:

  • 1、将字符串中和程序冲突的字符转为原文
  • 2、包含特殊功能的符号:换行:\n 制表符:\t -->tab键效果
  • 3、输出Unicode 编码的字符:最小的字\u4e00 一 --asci码:19968 最大的字\u9fa5 --ascii码:40869

2、大小写转换:

将字符串中每个字符统一的转为大写或者小写

  • 使用:只用程序不区分大小写,就要先统一的转为大写或小写,再作比较(比如做验证码)

  • 语法:大写/小写:var upper=str.toUpper/LowerCase;

3、获取字符串中指定位置的字符:

str.charAt(i); 等同于str[i];

4、获取字符串中指定位置的字符的ASCII码:

var ascii=str.charCodeAt(i);

通过ASCII码转回原文:var 原文=String.fromCharCode(ascii);

5、检索字符串:

检查索引,检查下标:获取关键字的下标

var i=str/arr.indexOf("关键字",starti);从starti位置开始,从左到右依次查找,starti可以省略,默认从0开始查找

返回值:找到了,返回找到的第一个关键字的下标,没找到,返回-1

作用:判断有无

数组也可以使用此方法,数组这个方法是后面加上的,老IE的数组就没有此方法

鄙视题:这个方法默认只能获取到第一个关键字的下标,如何获取所有关键字的下标:

var str='no zuo ni die no zuo no bibi';
var indedx=-1;
while((index=str.indexOf('no',index+1))!=-1){
    console.log('找到了,下标为:'+index);
}

6、拼接字符串

var newStr=str.concat("新字符串",..); 不如 +运算

7、截取字符串

var subStr=str/arr.slice(starti,endi+1);//左闭右开

var subStr=str.substring(starti,endi+1);//左闭右开,不支持负数

var subStr=str.substr(starti,n);//n代表截取的个数

8、替换字符串

var newStr=str.replace("固定关键字"/正则表达式,"新内容");//这个方法加上正则表达式后十分强大

9、切割/分割/分离字符串

作用:将字符串转为数组

var arr=str.split("自定义切割符");

注意:1、切割后,切割符就不存在了;2、如果切割符是""空字符串,则会切散每一个字符

10、去掉空白符

str.trim/trimStart/trimEnd();

11、扩展:JS如何创建元素:3步

1、创建空标签:var elem=document.createElement("elem");

2、为其设置必要的属性和事件: elem.属性名="属性值"; elem.on事件名=function(){操作};

3、挂载上树/渲染页面:父元素.appendChild(elem);

六、Math对象

专门提供了数学计算的API

强调:不需要创建,直接使用

属性:Math有一些属性涉及到科学计数法,但很少用到,常用的就Math.PI,π不需要自己创建,浏览器自己有

Math的API

1、取整:3种

1、上取整:超过一点点就取下一个整数
var num=Math.ceil(num);//小数位数不能超过15位,否则会下取整

2、下取整:无论超过多少,都会省略掉小数点后面的部分
var num=Math.floor(num);

3、四舍五入取整:var num=Math.round(num);//只看小数点第一位

  • 以上三个方法都很一般,都是取整,但只能取整

  • 取整的方式:以上三个+parseInt(str去掉单位)+num.toFixed(d);

  • num.toFixed(d); 优点:1、可以四舍五入,并保留指定位小数d 2、解决浏览器带来的舍入误差,例如:2-1.6=3.9999999999...这种情况可以使用toFixed来解决
    缺点:结果数一个字符串,可以与parseFloat()搭配使用

鄙视题:不允许使用toFixed()的情况下,自己封装一个函数,由用户传入数字,实现四舍五入:

function toFixed(num,d){
    num*=10**d;
    num=Math.round(num);
    num/=10**d;
    return num;
}
var result=toFixed(Math.PI,2);
console.log(result);

2、乘方和开方

乘方:Math.pow(底数,幂); --> 简化:底数**幂

开方:Math.sqrt(num);仅仅只能开平方

3、最大值和最小值

var max/min=Math.max/min(23,435,2331,56,3254,3);

问题:本身不支持数组参数

解决:Math.max/min.apply(Math,arr);apply具有打散数组的功能

4、绝对值

把负数转为正数

Math.abs(-1);

5、随机数

Math.random();在0-1之间取一个随机小数

搭配上parseInt,只能取到0,不能取到1

语法:parseInt(Math.random()*(max-min+1)+min);

只要网页有随机功能,就一定用到了随机数

七、Date对象

日期对象,提供了操作日期和时间的API

1、创建:4种

1、创建一个当前日期: var now=new Date();

2、创建一个自定义时间: 法一: var birth=new Date("year/month/date hours:minutes:seconds")

法二: var birth=new Date(year/month/date hours:minutes:seconds);月份0-11,0代表1月

3、复制一个日期:
为什么:日期的所有API都是直接修改原日期的,无法获得修改之前的日期
所以,在执行API之前先进行复制,然后再操作复制后的日期:
var end=new Date(start);

2、Date的API

分量:时间的单位

年月日星期:FullYear Month Date Day

时分秒毫秒:Hours Minutes Seconds Milliseconds

每一个分量都有 getXXX/setXXX 的方法

特殊:

  1. 取值范围:
    FullYear - 当前年份的数字
    Month - 0-11
    Date - 1-31
    Day - 0-6: 0为星期天,6星期六 Hours - 0-23
    Minutes、Seconds - 0-59

  2. Day,没有set方法

  3. 某个分量的加减操作
    date.setXXX(date.getXXX()+/-n)

  4. 格式化日期为本地字符串
    date.toLocaleString(); - 垃圾:具有兼容性问题,我们一般会选择自己创建一个格式化方法来格式日期
    用了此方法会失去一些东西:日期的自动进制、日期的API 但是你也会获得一些东西:字符串的API

八、定时器

1、周期性定时器

每过一段时间就会执行一次,先等后做

开启:timer=setInterval(callback,间隔毫秒数);

停止:clearInterval(timer);

2、一次性定时器

等待一段时间,只做一次就结束了

开启:timer=setTimeout(callback,间隔毫秒数);

停止:clearTimeout(timer);

同步技术:代码必须一行一行执行,前面没做完,后面就等着

异步技术:无论这块代码多么耗时,都不会卡住后面代码的执行

定时器是异步技术

九、BOM

Browser Object Model - 浏览器对象模型,专门用于操作浏览器,但使用不大多,远不如ES和DOM,浏览器很多操作都是自带的,而BOM没有标准

各个浏览器都有自己的定义,但大部分浏览器都是一致规范的,除了老IE(8-)

十、window对象

扮演着两个角色

1、全局对象:

保存着全局变量和全局函数

2、指代当前窗口本身:

属性:

1、获取浏览器的完整大小:outerWidth/outerHeight

2、*获取浏览器的文档显示区域的大小:innerWidth/innerHeight - 获取每台电脑的浏览器的文档显示区的大小

3、获取屏幕的完整大小:跟window没关系:screen.width/height; - 我们目前学习的都是浏览器应用(网页),并不会去做桌面应用

方法:

1、打开链接的新方式:

1、当前窗口打开,可以后退:
HTML:<a href="url">内容</a>
JS:open("url","_self");

2、当前窗口打开,禁止后退:
使用场景:比如电商网站,结账后不允许后退
HTML做不到,只有JS可以,也不是window能做到的:

  • history:当前【窗口的历史记录】,他其实可以做的事儿就是前进后退
  • location:当前【窗口正在打开的url】,有一个API:
    location.replace("新url");//叫做替换,不叫做跳转,不会产生历史记录,自然也不能后退了,但是网址替换了,网页必然会发生变化

3、新窗口打开,可以打开多个
HTML:<a href="url" target="_blank">内容</a>
JS:open("url","_blank");

4、新窗口打开,只能打开一个:
使用场景:比如电商网站,只允许用户打开一个结账页面
HTML:<a href="url" target="自定义一个name">内容</a>
JS:open("url","自定义一个name");
其实窗口的底层都是有一个名字的,如果打开了一个已经开着的名字的窗口的,他会把他关闭掉,再次打开

  • 学完这块的成果:
    1、以后的跳转,任何标签都可以 2、提升用户的体验感 3、a标签的其他用途:
    1、跳转 2、锚点 3、下载按钮:<a href="xx.exe/rar/zip/7z">下载</a> 4、打开图片和txt文档:<a href="xx.png/jpg/jpeg/gif/txt">打开图片和txt</a> 5、直接书写js-不需要绑定点击事件:<a href="javascript:js代码;">打开图片和txt</a>

2、打开新窗口/新链接:

newW=open("url","target","width=?,height=?,left=?,top=?");
特殊:
1、如果没有加第三个参数,那么窗口会和浏览器融为一体
2、如果你加了第三个参数,那么窗口会脱离浏览器独立存在

3、关闭窗口:window/newW.close();

4、改变新窗口的大小:newW.resizeTo(新宽,新高);

5、改变新窗口的位置:newW.moveTo(新X,新Y);

6、*window提供了三个框:

警告框:alert("警告文字"); 输入框:var user=prompt("提示文字"); 确认框:var bool=confirm("提示文字");

7、*****定时器也是window的

8、事件:

1、window.onload事件 - load - 加载:等待其他所有的资源加载完毕后才会执行的代码,放在里面的代码其实要最后才会执行

2、window.onresize事件 - 窗口如果大小发生了变化,就会触发,搭配上判断innerWidth可以理解为是js版本的css媒体查询

3、window.onscroll事件 - 滚动事件,一旦滚动就会触发 1、获取滚动条当前的位置:window.scrollY 2、获取元素距离页面顶部有多远:elem.offsetTop/offsetLeft

9、*****本地/客户端存储技术:

1、cookie:淘汰了,存储的大小只有2kb,而且操作极其麻烦,尤其要到处切割,只能最多保存30天

2、webStorage:H5带来了一个新特性,存储的大小有8mb,永久保存,而且非常简单
分类2种:

  • 1、sessionStorage - 会话级,只要浏览器一旦关闭,数据就会死亡了
  • 2、localStorage - 本地级,只要你不清空,就会永久存在 两者的用法是一模一样的,不用创建,直接可用

操作:
1、添加:xxxStorage.属性名="属性值";
2、读取:xxxStorage.属性名;
3、删除:xxxStorage.removeItem("属性名");
4、清空:xxxStorage.clear();