数组的基础②
创建数组 var arr = [值1,...];
var arr = new arr(值1,...);
第二种方法有一个坑:new arr(num);表示创建一个长度为num的空数组,里面没有任何东西,只有无数的undefined
题1:按值传递:var a=x; var b = a; 修改a,b变不变,或者修改b,a的值变不变?
答:如果传递的是原始类型,其实是复制了一个副本给对方,两者是互不影响的。
如果传递的是引用类型,其实是把自己的地址值给了对方,而两者是同一个地址值,一个修改,另一个也会修改
因为引用类型很大,比原始类型大的多,不可能保存在变量本地,只是保存了一个地址值而已。
引用类型在比较时,其实看的不是值,而是地址值在作比较。
题2:如何释放一个引用类型?一定要看清楚有几个变量引用着这个引用类型,每个变量都要释放后才能释放干净!
因为在JS底层有一个垃圾回收器,只有垃圾回收器的计数器为0的时候才会删除不要的数据。
建议:代码都要封装在一个函数内,函数中的一切变量都会释放。
索引数组:下标都是数字组成的数组。
**hash数组**
下标是可以自定义的
为什么:索引数组的下标无具体意义,不便于查找
如何使用:
1.创建:2步
先创建一个空数组:var arr = [];
为数组添加自定义下标并且赋值:arr["自定义下标"] = "新值";
2.访问:arr["自定义下标"]
3.强调:hash数组的length会失效,永远为0!
遍历hash数组不能再使用for循环了,必须使用for in 循环;for in它不需要设置从哪里开始,到哪里结束,纯自动化的,专门为了遍历hash数组而存在的。
4.for in 语法:
for(var i in arr){
i -> 下标
arr[i] -> 当前元素
}
for in 不仅可以遍历hash数组,还可以遍历索引数组。
**JS里面的一切东西都是对象,除了undefined和null。一切对象的底层都是hash数组。**
** 数组的API**
1. arr to str
var str = arr.join("自定义连接符");
笔试题:将数组里面的内容拼接成一段话/单词的无缝拼接,其实就是拼接了一个空字符串。
拼接数组:
将你传入的实参全部拼接到数组的末尾
语法:var newArr = arr.concat(值1,...);
特殊:1.不修改原数组,只会返回一个新数组
2.concat支持传入数组参数,悄悄的将传入的数组打散为单个元素再拼接
截取子数组:
只想要取出数组的某一部分使用
语法:var subArr = arr.slice(starti,endi+1);
特殊:
1.不修改原数组,只会返回一个新数组
2.含头不含尾
3.endi可以省略不写,表示从starti截取到末尾
4.starti和endi都可以省略不写,那么从头到尾完整的复制一份,此操作
也叫做深拷贝!复制了一个副本给对方,两者互不影响。
5.支持负数参数,-1代表倒数第一个
2.以下所有的API都会直接修改原数组
**删 插 替**
删除:var dels = arr.splice(starti,n);//n代表你要删除的几个
特殊:虽然它直接修改原数组,但是也有返回值,返回的是被删除数组组成的一个新数组。
替换:var dels = arr.splice(starti,n,新值1,...)
特殊:插入的元素和删除的元素,个数不必相等
插入:var dels = arr.splice(starti,0,新值1,...);
特殊:1.原stari位置的元素以及后续元素都会向后移动
2.尽量不要插入一个数组,会导致我们的数组一些是一维,一些是二维,导致我们遍历的时候极不方便。
**翻转数组**:arr.reverse();
例如:var arr = [2,9,5];
arr.reverse();
console.log(arr);//[5,9,2]
**数组的排序**
语法:arr.sort();
默认:将数组中的元素转为字符串,然后按位PK每个字符的Unicode号(ASCII码)
问题1:希望将数字升序排序:
arr.sort(function(a,b){
return a-b;
})
此函数叫做匿名回调函数
如果a-b>0;说明后一个大于前一个
如果a-b<0;说明后一个小于前一个
两者相等时,不需要交换位置
问题2:希望按照数字降序排序:
arr.sort(function(a,b){
return b-a;//前一个数减后一个数
})
强调:1.以后只要在网页上发现有排序功能,说明他的底层一定是一个数组,因为JS里面只有数组可以排序。
2.以后只要在网页上发现有随机功能,说明它底层一定有随机公式。
**添加元素和删除元素的新方式:**
arr.unshift(a,b,...);//添加元素,向前添加,添加到第一个元素的前面一个位置。缺点:导致其它元素的下标发生改变
arr.shift();//删除元素的新方式,向前删除,一次只能删除一个,也有返回值,返回的是删除的那个元素。缺点:导致其它元素的下标发生变化。
arr.push(a,b,c...);//添加元素,向后添加,添加到最后一个元素的后面。
arr.pop();//删除元素,向后删除,一次只能删除一个,也有返回值,返回的是删除的那个元素。
**ES5提供的3组6个API:**
1.判断:2个,判断的结果一定是一个布尔值
every:每一个,要求所有的元素都满足条件,结果才为true,只要有一个不满足则为false
语法:var bool = arr.every(function(val,i,arr){
//val - 当前的值
//i - 当前值的下标
//arr - 数组的本身
return 判断条件
})
some:有一些,只要有一个元素满足,则为true,类似于|| 或操作
var bool = arr.some(function(val,i,arr){
return 判断条件
})
2.遍历:拿到数组中的每个元素做相同或相似的操作
forEach - 直接修改原数组:
arr.forEach(function(val,i,arr){
操作;
})
map - 不修改原数组,返回一个新数组:
var newArr = arr.map(function(val,i,arr){
retrun 操作;
})
3.过滤和汇总
过滤:筛选出需要的部分,但和现实不一样,原数组不会变化
var subArr = arr.filter(function(val,i,arr){
retrun 判断条件;
})
汇总:var sum = arr.reduce(function(prev,val,i,arr){
retrun prev+val;
})
以上6个API是为简化for循环。
**ES6箭头函数:专门为了简化一切的匿名回调函数**
公式:function去掉,()和{}之间添加一个 => ,如果形参只有一个,那么()可以省略,
如果函数只有一句话,那么{}省略,如果函数体只有一句话并且是return,那么return和{}一起省略。
**二维数组**
数组的元素,又引用着另一个数组
何时使用:在一个数组内,再次细分每一个数组
创建:var arr = [["name","age","height"],["name","age","height"]];
访问:arr[行下标][列下标];
特殊:
面试题:列下标越界,返回undefined;行下标越界,得到一个报错,因为行下标越界其实已经undefined了,undefined没有资格加[]做操作。
遍历二维数组:
必然两层循环,外层循环控制行,内层循环控制列。
for(var r = 0;r<arr.length;r++){
for(var c=0;c<arr.length;c++){
console.log([r][c]);
}
}
Srting的概念
什么是字符串:多个字符组成的【只读】字符【数组】(所有的字符串中的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(面向对象)
***包装类型:专门用于将原始类型的值封装为一个引用类型的对象。
为什么undefined和null不能使用,因为它们没有包装类型。
String的API
转义字符: \
作用:将字符串中和程序冲突的字符转为原文。
包含特殊功能的符号:
换行:\n; 制表符:\t
*输出Unicode编码的字符:
汉字的第一个字:\u4e00;
汉字的最后一个字:\u9fa5;
*大小写转换:
将字符串中每个英文字符统一转为大写或小写
var 大写 = str.toUpperCase();
var 小学 = str.tolowerCase();
*获取字符串中指定位置的字符:
str.chatAt(i) === str[i];
**获取字符串中的指定位置的字符ASCII码:
var ascii = str.charCodeAt(i);
***通过ASCII码转回原文:
var 原文 = String.fromCharCode(ascii);
***检索字符串:检查索引 - 检查下标,获取关键字的下标
var i = str/arr.indexof("关键字",starti);///从starti位置开始,查找右侧第一个关键字的第一个字符的下标,starti可以省略,默认从0开始查找。
返回值:找到了,返回的第一个位置的第一个字符下标,
***没找到,返回-1,其实我们根本不关心下标为多少,只管下标为不为-1。
作用:***判断有没有,只要不希望有重复的就用它。
强调:数组也能用使用此方法,数组这个方法其实是后期才添加上的,原本此方法只有字符串才能使用,ie8及以下此方法不行。
***拼接字符串:var newstr = str.concat();
***截取字符串:3个
*var newStr=str/arr.slice(starti,endi+1);
str.substring(starti,endi+1);//几乎和slice一样,但不支持负数参数。
str.substr(starti,n);//n代表截取的个数,不必考虑含头不含尾。
***替换字符串:
var newstr=str.replace("固定关键字"/RegExp,"新内容");
***去掉开头和结尾的空白字符:
str.trim();
str.trimStart()/trimEnd();
*****切割/分割字符串*****:
作用:将字符串切割为数组:str <=> arr
var arr = str.split("自定义切割符");
特殊:
1.切割后,切割符就不在了
2.如果切割符写的是一个空字符串" ",会切散每一个字符。
*扩展
如何使用JS创建页面元素:3步 :深入数据渲染
1.创建空标签: var elem = document.createElement("标签名");
2.为其设置必要的属性和事件
elem.属性名="属性值";
elem.onclick事件名=function(){}
3.渲染到DOM树
父元素.appendChild(elem);
Math对象
专门提供了数学计算的API
强调:math不需要创建,直接使用,由浏览器的JS解释器自动创建。
API:1.取整:3种
向上取整:超过一点,就会取下一个整数 Math.ceil(num);但小数点位数不能超过15位,超过就失效。
向下取整:无论超过多少,都会省略小数部分。 Math.floor(num);
四舍五入:只看小数的第一位。 Math.round(num);
num.toFixed(d);//d代表保留的有效位数,而且也带有四舍五入
缺点:返回的结果是一个字符串,建议搭配parsefloat使用。
2.乘方和开方
乘方:Math.pow(底数,幂) === es9提供了简化:底数**幂;
开方:Math.sqrt(num);//只能开平方
3.最大值和最小值
var max/min=Math.max/min(a,b,c,d….);//在你传入的数里面直接找出最大值和最小值。
问题:默认不支持数组参数
解决:固定用法:
Math.max/min.apply(Math,arr);//apply具有打散数组功能。
或者Math.max/min(…arr);
4.绝对值:把负数转为正数
Math.abs(num);//可以是负数
5.***随机数:Math.random(); // 在0-1之间取一个随机小数
搭配上parseint,只能取0,不可能取到1,意味着取到最小值,而不是最大值。
公式:parseInt(Math.random()*(max-min+1)+min);
强调:只要网页中某一块带有随机功能,底层一定带有随机数。
Date对象:
日期对象,提供了可以操作日期和时间的API
创建:4种
1.创建当前时间:
var now=new Date();
2. *创建一个自定义时间:
var birth=new Date(“yyyy/MM/dd hh:mm:ss”);
3. 创建一个自定义时间:
var birth=new Date(yyyy,MM-1,dd,hh,mm,ss);//修正月份,从0-11月,0代表1月
4.复制一个日期:
为什么:日期的所有的API都是直接修改原日期的,无法获得修改之前的日期,
所以,在执行API之前都要先执行一次复制,然后再操作复制后的日期。
var end=new Date(start);
操作:
两个日期相减,得到一个毫秒差,换算出自己想要的任何一部分 - 日期的本质其实就是保存了一个毫秒数
创建日期的最后一种方式:var date = new Date(毫秒数);
**API**
分量:时间的单位
年月日星期: FullYear Month Date Day
时分秒毫秒: Hours Minutes Seconds MiiliSeconds;
每一个分量都有一对方法getXXX/setXXX
其中getXXX负责获取一个分量的值
SetXXX负责设置一个分量的值
特殊:
1.取值范围:FullYear – 当前年份的数字 Month – 0~11 Date – 1~31
hours – 0~23 Minutes, Seconds 0~59 Day – 0~6,0代表星期天,
外国人眼里星期天是一周的第一天
2.任何人都可以设置set ,但Day不可以设置setDay
3.如果希望对某个分类进行加减操作的话:date.setXXX(date.getXXX()+/-n);
4.格式化日期为本地字符串:
date.toLocalString(); 具有兼容性问题,我们一般会选择自己封装一个format函数进
行格式化,用了此方法会失去:日期的自动进制,以及日期的所有API,但是会得到字符串
的所有API。
** 定时器:**
1.周期性定时器:每过一段时间就会执行一次,先等再做,会反复执行,需要自己写停止才能停止。
开启:timer=setInterval(callback,间隔毫秒数);
停止:clearInterval
2.一次性定时器:
开启:timer=setTimeout(callback,间隔毫秒数);
停止:clearTimeout(timer);
BOM:Browser Object Model 浏览器对象模型
Window对象:
扮演着两个角色:一个页面和一个window
1.代替全局对象global,保存着全局变量和全局函数
2.指代窗口本身
属性:专门用于获取大小
*获取浏览器的完整大小:outerWidth/outerHeight;
*获取浏览器的文档显示区域(就是用户看到的部分)的大小:innerWidth/innerHeight
*获取屏幕完整大小:screen.width/height;
打开链接的新方式JS做法:
1.当前窗口打开,可以后退:open("url","_self");
2.新窗口打开,可以打开多个:open("url","_blank");
3.当前窗口打开,只打开一个页面:location.replace("新url")
使用场景:电商网站,结账后禁止后退。
4.新窗口打开,不可以后退,只打开一个:open("url","自定义name");
使用场景:电商网站,只允许用户打开一个结账界面。
3.a标签的其它用途:
下载:<a href = "xx.exe/zip/rar/7z"></a>
打开:<a href = "xx.txt/jpg/png/gif"></a>
4.打开新窗口/新链接:
var new = open("url","target","widrh=?,height=?,left=?,top=?");
特殊:1.如果没有传入第三个参数,那么浏览器和窗口会融入一体,浏览器多大,窗口就多大。
2.如果传入第三个参数,窗口和浏览器分离开,独立存在。
3.可以拿个变量保存住此窗口,以后用于其它操作。
5.关闭窗口:window/new.close();
6.改变新窗口的大小:new.resizeTo(新宽,新高);
7.改变新窗口的位置:new.moveTo(新X,新Y);
8.确认框:var bool = confirm("提示文字");
输入框:var user = prompt("提示文字");
警告框:alert("警告文字");
9.window.onscroll - 滚动事件,一旦滚动就会触发
*获取滚动条当前的位置:window.scrollY
*获取页面元素距离顶部有多远:elem.offsetTop/offsetLeft;
10.*****本地/客户端存储技术:
cookie:存储大小只有4KB,且只能保存30天,还需要到处切割。
WebStorage:H5带来的一个新特性:存储大小只有8MB,永久保存,操作简单。
WebStorage分两类:
1.sessionStorage:会话级,只要浏览器关闭,数据就会死亡。
2.localStorage:本地级,只要不清空,它就会永久存在。
操作:
1.添加:xxxStorage.属性名="属性值";
2.删除:xxxStorage.removeItem("属性名");
3.读取:xxxStorage.属性名;
4.清空:xxxStorage.clear();
扩展:
1.表单提交事件:
form.onsubmit=function(){
操作;
}
2.获取时间的毫秒数:date.getTime();