数组
1、创建数组:
直接量方式:var arr=[ ]
构造函数:var arr=new Array()
构造函数的方法:new Array(num);表示创建了一个长度为num的空数组,里面没有任何东西,只有无数的undefined
面试题:按值传递:var a=x;var b=a;修改a,b变不变或者反过来;
- 如果传递的原始类型,其实是复制了一个副本给对方,互不影响;
- 如果传递引用类型(函数,数组就是引用类型),因为引用类型很大,比原始类型大很多,不可能保存在变量本地,,只是保存了一个地址值而已,其实是赋值了自己的地址值给对方,两者用同一个地址值,一个改变另一个也会改变;
2、如何释放一个引用类型
一定要看清楚有几个变量在引用这个引用类型,每个变量都释放后才能释放干净;写代码都要封装为一个函数,函数的一切变量都会自动释放;
索引数组:下标都是数字组成的数组;
hash数组(关联数组):下标是可以自定义的
索引数组的下标无具体意义,不便于查找;
使用:hash数组的length失效了,永远为0;遍历hash数组,不能使用for循环,必须使用for in循环,for in循环不需要设置从哪里开始从哪里结束,纯自动化的,专门为遍历hash数组而存在的
for(var i in 数组名){
i//下标
数组名[i]//当前此元素;
}
for in 不止能遍历hash数组,还能遍历索引数组;但是索引数组尽量用for循环;hash数组再使用for in循环;
hash数组的原理: hash算法:将字符串计算出一个尽量不重复的数字;字符串相同则计算出来的数字也一定是相同的;
- 添加元素:将自定义下标交给hash算法,得到一个数字,直接将你要保存的数据保存到此地址保存起来
- 获取元素:将指定的下标交给hash算法,得到一个和当初保存时一样的数字,通过此地址找到你当初保存的数据,取出来使用;
js里面的一切东西都是对象,万物皆对象,除了undefined和null,一切对象的底层都是hash数组;
数组的API:前辈们预定义了很多方法,只有数组可用这些方法,只需要我们调用
- arr转str:var str=arr.join("自定义连接符") 固定套路:
- 将数组中的内容拼接成一句话/单词,无缝拼接,其实就是拼接了一个空字符串;
- 将数组拼接为DOM元素,数据渲染页面
var arr=["-请选择-","北京","上海","天津","南京"];
var str=""+arr.join("")+"";
Sel.innerHTML=str;
- 数组拼接:添加元素的新方式,将你传入的实参全部拼接到arr的末尾
var newArr=arr.concat();
- 不修改原数组,只会返回一个新数组;
- 含头不含尾;
- endi可以省略,如果省略,会从starti位置一直截取到末尾
- starti也可以省略,如果两个实参都省略,那么会从头到尾完全的复制一份,此操作也叫做深拷贝,复制一个副本给对方;
- 支持负数参数,-1代表倒数第一个
- 以上API都不会修改原数组
以下API都会修改原数组
3.删插替:删除:var dels=arr.splice(starti,n)//n代表删除的个数
特殊:虽然他直接修改原数组,但是也有返回值,返回的是被删除的数组组成的新数组,因为考虑到删除掉的东西刚好是我们需要的东西;;哪怕没有删除也会返回一个空数组;
插入:arr.splice(starti,0,新值);
特殊:
- 原starti位置的元素以及后续元素都会向后移动;
- 尽量不要插入一个数组,会导致数组一些事一维,一些事二维,遍历的时候不方便;
替换:var dels=arr.splice(starti,n,新值);
特殊:删除的个数和插入的个数必须相同;
-
翻转数组:arr.reverse(); 以后不用;
-
数组排序:
- 比试时,冒泡排序,前一个元素和后一个元素进行对比,如果前一个元素大与后一个元素就交换位置,但是做完一轮只有最大的一个数排在了最后面,所以要再开循环反复使用;固定公式:
var arr=[31,21,54,4376,69,8,8,65,643,52,3,321,5,47,69,87,643,524];
for(var j=1;j<arr.length;j++){
for(var i=0;i<arr.length-j;i++){
if(arr[i]>arr[i+1]){
var m=arr[i];
arr[i]=arr[i+1];
arr[i+1]=m
}
}
}
console.log(arr);
- 正式开发时:arr.sort();默认将数组中的元素转换为字符串后再按位PK每个字符的Unicode号
排序:arr.sort(function(){;匿名回调函数,回调函数不需要我们调用,已经创建好,我们只需要使用,而sort方法会悄悄的调用;
console.log(a);//后一个数字
// console.log(b);//前一个数字
return a-b;//如果a-b返回的是一个正数:说明后一个>前一个
//如果a-b返回的是一个负数,说明后一个<前一个
//如果a-b返回的是一个0,说明后一个==前一个
//而sort方法会根据你返回的正数、负数、0,来自动考虑要不要交换位置
})
sort方法会根据返回的正数,负数,和0来自动考虑要不要换位
强调:
- 只要网页上有功能带有排序,他的底层一定是数组,因为js中只有数组可以排序
- 只要网页上有随机的功能,那么他的底层一定用到了随机数公式
二级联动:
- select专属事件onchange-只有选中项发生变化才会触发
- select专属属性selectedIndex-获取当前选项下标
- 必须使用二维数组再次细分每个分类
数组的API
6.栈和队列:添加元素和删除元素的新方式:
栈:其实就是数组,只不过一端封闭了,只能从另一端进出
使用:
开头进:arr.unshift(新值);添加元素的新方式,向前添加,缺点:导致其余元素的下标都发生变化
开头出:arr.shift(新值);删除元素新方式,向前删除,一次只能删除一个;缺点:导致其余元素下标都发生变化
结尾进:arr.push(新值);添加元素新方式,向后添加;
结尾出:arr last=arr.pop;删除元素新方式,向后删除;
队列,也是数组,只不过一端进,另一端出:开头进结尾出或者结尾进开头出;
二维数组:数组的元素又引用着另一组数组;在一个数组中,希望再一次细分每个分类;
var arr=[
["判",18,900],
["王",19,1000],
["干",20,700]
];
访问:arr[行下标][列下标];
特殊:列下标越界,返回undefined,行下标越界得到的是一个报错,因为行下标越界已经得到了一个undefined,undefined没有资格再做任何操作;
遍历二维数组:必然得到两层循环,外层循环控制行,内层循环控制列;
for(var r=0;r<arr.length;r++){
for(var c=0;c<arr[r].length;c++){
console.log(arr[r][c]);
}
}
ES5提供的6个API
- 判断:2个
every:每一个,要求所有元素都满足条件才会为true,只要有一个条件不满足则为false,类似与&&运算
var bool=arr.every(function(val,i,arr){
//val - 当前的值
//i - 当前的值的下标
//arr - 当前数组本身
return 判断条件;
})
some:有一些,要求只要有一个元素满足条件就为true,所有条件都不满足则为false;类似与||运算;
var bool=arr.some(function(val,i,arr){
return 判断条件;
})
- 遍历:拿到数组中的每个元素做相同或相似的操作
- forEach一般直接修改原数组
arr.forEach(function(val,i,arr){
直接做你想要的操作;
})
-map-不修改原数组,返回一个新数组
var newArr=arr.map(function(val,i,arr){
return 直接做你想要的操作;
})
- 过滤和汇总:
- 过滤:筛选出你想要的部分,但是和现实不一样的是原数组不会发生改变
筛选出你需要的部分,但是和现实不一样的是原数组并不会发生变化
var subArr=arr.filter(function(val,i,arr){
return 判断条件;
})
- 汇总:
var result=arr.reduce(function(prev,val,i,arr){
return prev+val;
},基础值)
ES6箭头函数:简化一切匿名回调函数
固定公式:function去掉,()和{}之间添加=>,如果形参只有一个,那么()也可以省略,如果函数体只有一句话,那么{}也可以省略,如果函数体只有一句话并且是return,那么return和{}都可以省略;
4. string的概念:
什么是字符串:多个字符组成的【只读】字符【数组】(只读:明天我们要学习的所有的字符串的API都不会修改原字符串,都会返回一个新的字符串)
和数组有相同点:
1、字符串中的个数:str.length;
2、获取字符串中的某个字符:str[i];
3、遍历字符串
4、所有数组不修改原数组的API,字符串也可以使用(concat、slice)
和数组也有很多不同的地方:
所有数组的直接修改原数组的API,字符串都不可以使用,比如排序只有数组可以使用,但是字符串也有很多很多属于自己的API
引用/对象类型11个:String Number Boolean -> 包装类型Array Function Date(日期) Math(数学) RegExp(正则:验证)Error(错误)Object(面向对象开发方式)
Global(全局对象)- 只有在浏览器中被window对象代替了, 自然保存着全局变量和全局函数,只不过window可以省略不写,有一天我们会去学习node.js这个后端语言,而在node.js中全局对象就叫做global
包装类型:
专门用于将原始类型的值封装为一个引用类型的对象的
为什么:原始类型的值原本就是没有任何属性和方法,意味着原始类型本身是不支持.去做任何操作的但是前辈们发现字符串经常会被我们程序员所操作,为了方便我们程序员将这三个人提供了包装类型(提供了属性和方法)
- 何时使用:只要你试图使用原始类型的变量调用属性或方法的时候,自动包装
- 何时释放:方法调用完毕后,自动释放包装类型,又变成了原始类型
5.stringAPI:字符串可以使用的函数
作用:
- 将字符串中和程序冲突的字符转为原文"""
- 包含特殊功能的符号:换行:\n
- 输出unicode编码的字符:\u4e00 - ascii码:19968
2、大小写转换:将字符串中每个字符统一转换为大写或者小写;只要程序不区分大小写,就要先统一转为大写或者小写再比较;
大写:var upper=str.toUpperCase();
小写:var upper=str.toLowerCase();
3、获取指定位置的字符:str.charAt(i)===str[i];
4、获取字符串中指定位置的字符的ASCII码:var ASCii=str.charCodeAt(i);
通过ASCII码转原文:var 原文=String.fromCharCode(ascii);
5、检索字符串:检查索引,检查下标;获取关键字的下标
var i=str.indevof(“关键字”,starti);
- 从starti位置开始,检测右侧第一个关键字的第一个字符位置
- starti可以省略,默认从0位置开始查找;
- 返回值:找到了,返回第一个关键字对的第一个字符位置;没找到,返回-1,不用关心小标的多少,只用看小标为不为-1;
- 作用:判断有没有
- 强调:数组也能使用此方法,数组这个方法是后期才加上的,原本此方法只有字符串可用,老版本的IE浏览器就没有此方法;
笔试题:默认只能获取第一个关键字的下标,如何获取关键字的下标?
var str="no zuo no die no can no bibi no";
var index=-1;
while((index=str.indexOf("no",index+1))!=-1){
console.log("找到了,下标为:"+index);
}
6、拼接字符串:var newstr=str.concat(“新字符串”,...);不如+运算
7、截取字符串3个:
- var substr=str/arr.slice(starti,endi+1);用法和数组一致;
- str.substring(starti,endi+1);用法几乎和slice一致,但是不支持负数参数;
- str.substr(starti,n); n代表截取的个数,不必考虑含头不含尾;
8、替换字符串:本身这个方法非常的强大,暂时没有学过正则表达式,所以只能替换固定的关键字;
var newstr=str.splace("固定关键字/正则表达式",新内容);
9、切割/分割/分隔字符串:将字符串转换为数组;var arr=str.split("自定义切割符");
- 切割后切割符就不见了
- 如果切割符写的是"",则会切散每个字符;
10、去掉空白字符:str.trim/trimStart/trimEnd();
扩展:js如何创建元素:
- 创建空白标签:var elem=document.creatElement("标签名");
- 为其设置必要的属性和事件:elem.属性名="属性值";elem.on事件名=function(){操作} 3.挂载上树/渲染页面:父元素.appendchild(elem);
Math对象:专门提供了数学计算的API
- 强调:不需要创建,直接使用
- 属性:Math的一些属性,涉及到科学计数法,但是几乎用不到,只有Math.pi能用到,浏览器自带的;
API取整:
- 上取整:超过一点点就取下一个整数;var num=Math.cell(num);//小数点位数不能超过15位,否则此方法只能取整,不能取上整;
- 取下整:无论超过多少,都会省略小数部分;var num=Math.floor(num);
- 四舍五入取整数:var num=Math.round(num);//只看小数位数的第一位
取整方式:以上三个+*parseInt(str去掉单位)+*num.toFixed(d);
num.tofixed(d)优点:可以四舍五入,并且保留指定小数位数;可以解决浏览器带来的舍入误差;结果是一个字符串,可以搭配parseFloat使用;
笔试题:在不使用to.fixed的情况下,自己封装一个函数,由用户传入数字和保留位数,实现四舍五入的操作;
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);
乘方和开方:
- 乘方:Math.pow(底数,幂);简化:底数**幂
- 开方:Math.sqrt(num),仅仅只能开方;
最大值和最小值
var max/min=Math.max/min(a,b,c,d,e,f,g);自动在你传入的数字中比较出最大值和最小值;
- 问题:本身不支持数组参数
- 解决:固定用法:Math.max/min.apply(Math,arr);//apply具有打散数组的功能
- 4、绝对值:把负数转为正数;Math.abs(-1);//1
随机数
- Math.random(); 在0-1之间取一个随机的小数,搭配上parseInt,只能取到0,但是不可能取到1,意味着取不到最大值
- 公式:parseInt(Math.random()*(max-min+1)+min)
- 强调:只要以后网页中某一块有随机的功能,他的底层一定用到了随机数;
Date对象:提供了操作日期和时间的API
创建:
- 创建当前日期:var now=new Date();
- 创建一个自定义日期;var birth=new Date("yyyy/mm/dd hh:mm:ss);
- 创建一个自定义时间:var birth=new Date(yyyy,mm,dd,hh,mm,ss);会修改月份,0代表一月;
- 复制一个日期:日期的所有API都是直接修改原日期的方法,无法获得修改之前的日期,所以在执行API之前都要先进行复制,然后再操作复制后的日期;var end=new Date(start);
使用:两个日期之间可以相减,大减小,得到一个毫秒差,换出你想要的任何一部分日期,本质就是保存了一个毫秒差,做倒计时的关键;创建日期最后一种方式:var date=new Date(毫秒数);
API
分量:事件的单位
年月日星期时分秒毫秒:FullYear Month Date Day Hour Minutes Seconds Milliseconds;
每个分量都有一对get/set的方法;get负责获取分量的值;set负责设置分量的值;
- 取值范围:
- FullYear-----当前年份的数字
- Month------0-11
- Date-------1-31
- Day--------0-6
- Hours------0-23
- Minutes,Seconds-------0-59
超出范围会自动进制
- Day没有set方法
- 如果希望对某个分量进行加减操作:date.setXXX(date.getXXX()+/-n);
- 格式化日期为本地字符串;date.toLocaleString(); - 垃圾:具有兼容性问题,我们一般会选择自己创建一个格式化方法来格式日期
定时器
1、周期性定时器:每过一段时间就会执行一次,先等后做
开启:timer=setInterval(callback,间隔毫秒数);
停止:clearInterval(timer);
2、一次性定时器:等待一段时间,只会做一次就结束了
开启:timer=setTimeout(callback,间隔毫秒数);
停止:clearTimeout(timer);
同步技术:代码必须一行一行的执行,前面没做完,后面就等着定时器是我们第一次见到的异步技术:无论我这一块代码多么的耗时,也不会卡住后续代码
Bom
Brower Object Model:浏览器对象模型,专门用于操作浏览器的,但是使用的不多,远不如ES和DOM,浏览器很多操作都是自带的;而且BOM没有标准,各个浏览器都有自己的标准,但是大部分浏览器都是一致规范的;
window对象:两个角色
- 全局对象:保存着全局函数和全局变量
- 指代当前窗口本身
属性:
- 获取浏览器的完整大小:outerWidth/outerHeight
- 获取浏览器的文档显示区域的大小:innerWidth/innerHeight - 获取每台电脑的浏览器的文档显示区的大小
- 获取屏幕的完整大小:跟window没关系:screen.width/height; - 我们目前学习的都是浏览器应用(网页),并不会去做桌面应用
方法: 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");
其实窗口的底层都是有一个名字的,如果打开了一个已经开着的名字的窗口的,他会把他关闭掉,再次打开
- 以后得跳转,任何标签都可以
- 提升用户的体验感
- 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、本地/客户端存储技术:
cookie:淘汰了,存储的大小只有2kb,而且操作极其麻烦,尤其要到处切割,只能最多保存30天
webStorage:H5带来了一个新特性,存储的大小有8mb,永久保存,而且非常简单
2种分类:
1、sessionStorage - 会话级,只要浏览器一旦关闭,数据就会死亡了
2、localStorage - 本地即,只要你不清空,就会永久存在
两者的用法是一模一样的,不用创建,直接可用
操作:
1.添加:xxxStorage.属性名="属性值"; 2.读取:xxxStorage.属性名; 3.删除:xxxStorage.removeItem("属性名"); 4.清空:xxxStorage.clear();