JS第二周总结

81 阅读12分钟

数组的基础

创建数组
  1. 直接量:var arr=[值1,...];用的比较多
  2. 构造函数:var arr=new Array(值1,...);
特殊

按值传递:

  1. 如果传递的是原始类型其实是复制了一个副本给对方,两者互不影响的;
  2. 如果传递的是引用类型:js中不是原始类型,就是引用类型(函数、数组........都是引用类型)- 浅拷贝
  3. 因为引用类型很大,比原始类型要大得多,不可能保存在变量本地,只是保存了一个【地址值】而已
  4. 其实是把自己的地址值赋值给了对方,而两者使用的是同一个地址值,一个人修改,另一个也会跟着变化
  5. 引用类型,在比较时,其实看的不是值,而是看的地址值在做比较

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

hash(关联)数组:下标是可以自定义的

为什么使用:索引数组的下标无具体的意义,不便于查找

如何使用:

1. 创建:2步

先创建一个空数组:var arr=[];
为数组添加自定义下标并且赋值:arr["自定义下标"]=新值;

2、访问:arr["自定义下标"];

3、强调:hash数组的length会失效,永远为0

遍历hash数组,不能再使用for循环了,必须使用for in循环 - 其实for in袍哥并不爱称呼他是一个循环,因为它不需要设置从哪里开始,到哪里结束,纯自动化的,专门为了遍历hash数组而存在的

语法:

for(var i in arr){
i->下标
arr[i]->当前次元素
}

特殊

不止hash数组可以遍历,索引数组也可以遍历

索引数组依然使用for循环,hash数组再使用for in

hash数组的原理

hash算法

将字符串,计算出一个尽量不重复的数字(地址值)
字符串内容相同,则计算出来的数字也一定相同
添加元素:js解释器会将自定义下标交给hash算法,得到一个数字(地址值),直接将你要保存的数据放到此地址之中保存
获取元素:js解释器会将指定的下标再次交给hash算法,得到了一个和当初保存时完全一样的数字(地址值),通过此地址值就可以找到你当初保存的数据了,取出来使用了

JS里面一切东西都是对象,万物皆对象,除了undefined和null,!!!!一切对象的底层都是hash数组!!!!

数组的API

前辈们预定义了很多方法,等待我们学习,我们程序员只需要学会如何使用,就可以直接用上 - 这些方法只有数组可以使用

1.自定义连接符

不修改原数组的,只会返回一个新数组

arr to str:

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

固定套路:2个

将数组里面的内容拼接为一句话/单词 - 无缝拼接,其实就是拼接了一个空字符串

  var arr=["h","e","l","l","o"," ","w","o","r","l","d"];
  console.log(arr.join(""));

将数组拼接为DOM页面元素 - 第一次遇到数据渲染页面,这仅仅只是数据渲染的基础 - 一个好的数据结构能极大的提升程序员的开发效率

  var arr=["-请选择-","北京","南京","西京","东京","重庆"];
  var str="<option>"+arr.join("</option><option>")+"</option>";
  sel1.innerHTML=str;

2.拼接数组:添加元素的新方式

不修改原数组的,只会返回一个新数组

 将你传入的实参全部拼接到数组的末尾
 语法:var newArr=arr.concat(新值1,arr1,...);
 特殊:
 1、不修改原数组,只会返回一个新数组
 2、concat支持传入数组参数,悄悄将的你传入的数组打散为单个元素再拼接

3.截取子数组:只想要取出数组的某一部分使用

不修改原数组的,只会返回一个新数组

 根据你传入的开始下标一直截取到结束下标
 语法:var subArr=arr.slice(starti,endi+1)
 特殊:
1、不修改原数组,只会返回一个新数组
2、含头不含尾
3、endi可以省略不写,如果不写,则从starti截取到末尾
4、starti和endi可以省略不写,那么从头到尾完整的赋值一份,此操作叫做深拷贝!复制了一个副本给对方,两者不会相互影响
5、支持负数参数,-1代表倒数第一个
    

4.删插替:

【删除】:var dels=arr.splice(starti,n);//n代表你要删除几个
特殊:虽然他直接修改原数组,但是也有返回值,返回的是被删除的数组组成的一个新数组,因为前辈们考虑到有可能删掉的就是你刚需要的,哪怕没有删除也会返回一个空数组

【插入】:var dels=arr.splice(starti,0,新值1,...);
特殊:
   1、原starti位置的元素以及后续元素都会被向后移动
   2、尽量不要插入一个数组,会导致我们的数组一些是一维,一些是二维,导致我们遍历的时候极不方便
【替换】:var dels=arr.splice(starti,n,新值1,...);
特殊:1、插入的元素和删除的元素,个数不必相等

 

5.翻转数组:arr.reverse(); 垃圾

6.数组的排序

 1、冒泡排序:前一个元素和后一个元素进行比较,如果前一个>后一个,两者就交换位置,发现就算做完一
    轮也只是将最大的数字放到了最后,所以还要再次开启循环,才能把每一个都排好.
		公式:
		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+1];
					arr[i+1]=arr[i];
					arr[i]=m;
				}
			}
		}
                    
  2、正式开发中:数组的API:arr.sort();
     默认:将数组中的元素转为字符串,然后再按位PK每个字符的unicode号(ASCII码)
     问题1:希望按照数字升序排序:
         arr.sort(function(a,b){此函数叫做匿名回调函数,回调函数不需要我们程序员调用,由前辈们创建好,我们学习如何使用即可,其实前辈们的sort方法,底层里面有一个形参,会接住我们传入的这个回调函数,前辈们悄悄的帮我们调用了,所以不需要程序员自己调用
         console.log(a);//后一个
         console.log(b);//前一个
         return a-b;//如果a-b返回的是一个正数,说明后一个>前一个
         如果a-b返回的是一个负数,说明后一个<前一个
         如果a-b返回的是一个0,说明后一个==前一个
         而sort方法会根据你返回的正数、负数、0,自动考虑要不要交换位置
         
         问题2:希望按照数字降序排序:			
			arr.sort(function(a,b){
				return b-a;
			})
         特殊:
              1、以后只要在网页上发现有排序功能,说明他的底层一定是一个数组,因为JS里面只有数组可以排序
              2、以后只要在网页上发现有随机功能,说明他的底层一定用到了随机数公式

7.栈和队列:添加元素和删除元素的新方式:

 栈:  其实就是数组,只不过是一端封闭,只能从另一端进
 如何使用:
           开头进:arr.unshift(新值1,...);//添加元素的新方式,向前添加,缺点:导致其他元素的下标都会发生变化
           开头出:var first=arr.shift();//删除元素的新方式,向前删除,一次只能删除一个,也有返回值,返回的是删除的那个元素,缺点:导致其他元素的下标都会发生变化

           结尾进:arr.push(新值1,...);//添加元素的新方式,向后添加
           结尾出:var last=arr.pop();//删除元素的新方式,向后删除,一次只能删除一个,也有返回值,返回的是删除的那个元素


队列:其实就是数组,只不过只能从一端进入,从另一端出去
何时:按照先来后到的顺序拿取数据
如何使用:
         开头进:arr.unshift(新值1,...);//添加元素的新方式,向前添加,缺点:导致其他元素的下标都会发生变化
         结尾出:var last=arr.pop();//删除元素的新方式,向后删除,一次只能删除一个,也有返回值,返回的是删除的那个元素
         结尾进:arr.push(新值1,...);//添加元素的新方式,向后添加
         开头出:var first=arr.shift();//删除元素的新方式,向前删除,一次只能删除一个,也有返回值,返回的是删除的那个元素,缺点:导致其他元素的下标都会发生变化
       

8.ES5(2014年)为数组提供了3组6个API:

1、判断: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 判断条件;
			})
                            
 2、遍历:拿到数组中的每个元素做相同 或 相似的操作
                 forEach - 直接修改原数组:
                 arr.forEach(function(val,i,arr){
				操作
			})

                  map - 不修改原数组,返回一个新数组
                           var newArr=arr.map(function(val,i,arr){
                                          return 操作;
                                          })
 3、过滤和汇总:
                过滤:筛选出你需要的部分,但是和现实不太一样,原数组是不会变化的!
			var subArr=arr.filter(function(val,i,arr){
				return 判断条件;
			})
                汇总:
                     var sum=arr.reduce(function(prev,val,i,arr){
				return prev+val;
                                    })
                                    
                        这6API都是为了简化一个人,for循环!!!!!!!!!!!!!!!!       

二维数组:数组的元素,又引用着另一个数组

何时使用:在一个数组内,再次细分每个分组 创建: var arr=[[],[],[]];

访问: arr[行下标][列下标];

遍历二维数组:

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

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

String的概念:

字符串和数组有相同点

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

和数组也有很多不同的地方:所有数组的直接修改原数组的API,字符串都不可以使用,比如排序只有数组可以使用

引用/对象类型:11个

String/ Number/ Boolean -> 这三个人具有包装类型
Array Function Date(日期) Math(数学) RegExp(正则:验证)
Error(错误)
Object(面向对象)
Global(全局对象)

StringAPI/字符串的API:

*1、转义字符:*

作用:
1、将字符串中和程序冲突的字符转为原文
			"\""	'\''
2、包含特殊功能的符号
     换行:\n
         制表符:\t	大空格,跟你敲tab效果是一样的
3、输出unicode编码的字符
      汉字的第一个字:\u4e00	->	ascii码:19968
  汉字的最后一个字:\u9fa5	->	ascii码:40869                         

2、大小写转换:

将字符串中每个英文字符统一的转为大写 或 小写
何时:只要程序不区分大小写,就要【先统一】的转为大写 或 小写,再比较(做验证码)
如何:
		var 大写=str.toUpperCase();
		var 小写=str.toLowerCase();

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,其实我们根本不关心下标为多少,我们只管下标为不为-1
      
作用:判断有没有,只要你不希望有重复的就用它
强调:数组也能使用此方法,数组这个方法其实是后期才添加上的,原本此方法只有字符串可用,比如老IE(8以前)的数组就没有此方法

6、拼接字符串:

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

7、截取字符串:3个

var newStr=str/arr.slice(starti,endi+1);//和数组的用法一模一样
str.substring(starti,endi+1);//几乎和slice一样,但是不支持负数参数
str.substr(starti,n);//n代表截取的个数,不必考虑含头不含尾

8、替换字符串:

var newStr=str.replace("固定关键字"/RegExp,"新内容")

9、去掉开头结尾的空白字符:

str.trim();
str.trimStart();
str.trimEnd();

10、切割/分割字符串

作用:将字符串切割为数组:str<=>arr
var arr=str.split("自定义切割符");
特殊:
    1、切割后,切割符就不存在了
    2、如果你的切割符写的就是一个空字符串"",切散每一个字符
    

Math对象:专门提供了数学计算的API

强调:Math不需要创建,直接使用,由浏览器的JS解释器自动创建

属性:Math有一些属性,涉及到科学计数法,但是几乎用不到,只有Math.PI可能会用到 === 3.1415926.... 这一串数字不需要你自己创建

API:

1、取整:

   1、上取整:超过一点点,就会取下一个整数
   Math.ceil(num);//小数点位数不能超过15位,否则会失效
   2、下取整:无论超过多少,都会省略小数点部分
   Math.floor(num);
   3、四舍五入取整:
   Math.round(num);//只看第一位小数
   
以上三个方法:都是在取整,而且只能取整
目前我们学过的取整方式:以上三个;*parseInt(str);*num.toFixed(d);num.toFixed(d);
优点:
     1、d代表保留的小数位数,而且也带有四舍五入的功能
     2、解决浏览器带来的舍入误差,计算机很笨,但是他的记忆力很强,而且速度很快,笨在何处?比如:2-1.6===	0.3999999999999
缺点:返回的结果是一个字符串,建议搭配parseFloat使用

2、乘方和开方

乘方:Math.pow(底数,幂)	===	ES9提供了简化:底数**幂
开方:Math.sqrt(num);//只能开平方

3、最大值和最小值:

var max/min=Math.max/min(a,b,d,c,e,f,g...........);//自动在你传入的数字中找到最大值或最小值
问题:默认不支持数组参数
解决:固定用法:Math.max/min.apply(Math,arr);//apply具有打散数组的功能

4、绝对值:把负数变成整数

Math.abs(num)

5、随机数:

Math.random(); -
在0~1之间取一个随机小数
搭配上parseInt,只能取到0,不可能取到1,意味着可以取到最小值,而取不到最大值
公式:parseInt(Math.random()*(max-min+1)+min);
强调:只要网页中某一块带有随机功能,那么他的底层一定用到了随机数

Date对象:日期对象

1.创建

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

2、操作:

  1. 两个日期对象之间可以相减,得到一个毫秒差(大-小),换算出自己想要的任何一部分 - 日期的本质其实就是保存了一个毫秒数(做出倒计时的关键)

  2. 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
    Day0~60代表星期天,外国人的眼里星期天是一周的第一天
    
  2. 任何人都可以set,唯独Day没有set操作

  3. 如果希望对某个分类进行加减操作的话

    date.setXXX(date.getXXX()+/-n)
    
  4. 格式化日期为本地字符串:

    date.toLocaleString(); - 垃圾,具有兼容性问题,我们一般会选择自己封装一个format函数来进行格式化用了此方法会失去一些东西:日期的自动进制,以及日期所有的API但是你也会得到一些东西:字符串所有的API,你可以解锁更多的操作(替换、截取、切割...)
    

定时器:

1、周期性定时器:

每过一段时间就会执行一次,先等再做,会反复执行,需要自己写停止才能停止
开启:timer=setInterval(callback,间隔毫秒数);
停止:clearInterval(timer);

2、一次性定时器:

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

BOM:

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

outerWidth/outerHeight;

2、获取浏览器的文档显示区域(用户能看到的部分)的大小:

innerWidth/innerHeight;

3、获取屏幕的完整大小:

 screen.width/height;

打开链接的新方式:

1、当前窗口打开,可以后退

HTML:<a href="">内容</a>
JSopen("url","_self");

2、当前窗口打开,禁止后退

location.replace("新url");

3、新窗口打开,可以打开多个

HTML:<a href="" target="_blank">内容</a>
JS:open("url","_blank");

4、新窗口打开,只能打开一个

HTML:<a href="" target="自定义name">内容</a>
JS:open("url","自定义name");

打开新窗口/新链接:

var newW=open("url","target","width=?,height=?,left=?,top=?");

关闭窗口:

window/newW.close();

改变新窗口的大小:

newW.resizeTo(新宽,新高);

改变新窗口的位置:

newW.moveTo(新x,新y);

window还提供了三个弹出框

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

window的专属事件

window.onresize:

创建如果大小发生了变化,就会触发,搭配上上面的innerWidth,我就可以判断现在窗口的大小不同,做不同的操作,他就是css3媒体查询的底层原理

window.onscroll:滚动事件,一旦滚动就会触发

1、获取滚动条当前的位置:window.scrollY
2、获取元素距离页面顶部有多远:elem.offsetTop/offsetLeft

本地/客户端存储技术:

1、sessionStorage - 会话级,只要浏览器一旦关闭,数据就会死亡

2、localStorage - 本地级,只要你不清空他,他就永久存在

操作:

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