JS代码第二周知识回顾

51 阅读17分钟

Day01

1.***数组(填坑):

1.创建数组:

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

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

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

2.***面试题:按值传递:var a=x; var b=a;修改a, b变不变,或者修改b, a变不变,传递的如果是原始类型:其实就是复制了一个副本给对方,两者互不影响. 传递的如果是引用类型:js中不是原始类型,就是引用类型(函数、数组,都是引用类型)-这是浅拷贝因为引用类型很大,比原始类型大的多,不可能保存在变量本地,只是保存了一个地址值而已,其实是赋值了自己的地址值给对方,两者用的是同一个地址值,一个修改另一个也会变化

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

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

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

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

2.***hash数组(关联数组):下标是可以自定义的,为什么:索引数组的下标无具体的意义,不便于查找

如何使用:1.创建:2步

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

2.访问元素:arr["自定义下标"];

3.强调:hash数组的length失效了,永远为0! 遍历hash数组:不能使用for循环,必须使用for in循环-其实for in 代老师不爱称呼他叫做一个循环,因为它不需要设置从哪里开始到哪里结束,纯自动化的,专门为了遍历hash数组存在的

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

4.***hash数组的原理:

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

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

5.js里面一切的东西都是对象,万物皆对象,除了undefined和null,[一切对象的底层都是hash数组]学习这块最大的目的:为了对象做准备工作

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

    1.*arr转str:
    var str=arr.join("自定义连接符")
    固定套路:2个
    
    1.笔试题:将数组里面的内容拼接成一句话/单次-无缝拼接,其实就是拼接了一个空字符串
    var arr=["h","e","l","l","o"," ","w","o","r","l","d"];
    var str=arr.join("");
    console.log(str);
    
    2.将数组拼接成DOM页面元素-第一次遇到数据渲染页面
    
    //拿数据
    
    var arr=["-请选择-","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆","北京","南京","西京","东京","重庆"]
    
    //将数组拼接为页面标签字符串
    var str="<开始标签>"+arr.join("</结束标签><开始标签>")+"</结束标签>";
    //巧了:innerHTML能够识别标签
    sel.innerHTML=str;
    
    
    2.*数组拼接:添加元素的新方式
    将你传入的实参全部拼接到arr的末尾
    var newArr=arr.concat(新值1,arr1,...);
    
    特殊:
    1.不修改原数组,只会返回一个新数组
    2.concat支持传入数据参数,悄悄的将你传入的数组打散为单个元素在拼接
    
    3.*截取子数组:
    根据你传入的开始下标截取到结束下标
    var subArr=arr.slice(starti,endi+1);
    特殊:1.不修改原数组,只会返回一个新数组
    2.含头不含尾
    3.endi可以省略不写,如果省略,会从starti位置一直截取到末尾
    4.starti也可以省略,如果两个实参都省略,那么会从头到尾完全的复制一份:此操作也叫做深拷贝-复制了一个副本给对方
    5.支持负数参数,-1代表倒数第一个
  

以上的api都是不修改原数组的

以下的api都是会修改原数组

4.*删插替

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

插入:arr.splice(starti,0,新值,...);

特殊:删除的个数和插入的个数不必相同

5.翻转数组:arr.reverse();今日一见,此生无缘

6.数组排序:

    1.笔试题:冒泡排序:前一个元素和后一个元素进行对比,如果前面一个>后一个,两者就交换位置,但是昨晚一轮发现只有最大的一个数字到了最后,所以再开循环反复使用,固定公式:
    
    var arr=[31,34,2,4,45,56,7878,45343,78989,5,65,6,4454353];
    for(var j=1,j<arr.length;i++){
    for(var i=0;i<arr.length-j;i++){
    if[i]>arr[i+1]{
    var m=arr[i];
    arr[i]=arr[i+1];
    arr[i=+1]=m
    }
    }
    }
    console.log(arr)

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

默认:将数组中的元素转为字符串后,在按位PK每个字符的unnicode号(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.以后网页上有随机的功能,那么他的底层一定是用到了随机数公式!

Day02

1.*****数组的API:

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

栈:其实就是数组,只不过是一端封闭了,只能从另一端进出

何时:现实生活中,情况不多:电梯、旅游巴士...优先使用最新的数据

如何使用:开头进:arr.unshift(新值,...);//添加元素的新方式,向前添加,缺点:导致其余元素的下标都发生变化

开头处:var first=arr.shift();//删除元素的新方式,向前删除,一次只能删除一个,缺点:导致其余元素下标都发生变化

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

结尾处:var last=arr.pop();//删除元素的新方式,向后添加

队列:其实就是数组,只不过一端进,从另一端出:

    开头进:arr.unshift(新值,...);
    结尾处:var last=arr.pop();
    
    结尾进:arr.push(新值,...);
    开头出:var first=arr.shift();
    

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

何时:在一个数组,希望再次细分每个分类

创建:

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<[r].length;c++){
        console.log(arr[r][c]);
    }
}

3.Es5还提供了3组6个API:

1.判断:2个

  every:每一个,要求所有元素都满足条件才会为true,只要有一个不满足则为false,非常类似于我们的&&
  var bool=arr.evry(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 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

***包装类型:抓们用于将原始类型的值封装为一个引用类型的对象的

为什么:原始类型的值原本就是没有任何属性和方法,意味着原始类型本身是不支持去做任何操作的

但是前辈们发现字符串经常会被我们程序员所操作,为了方便我们程序员将这三个提供了包装类型(提供了属性和方法)

何时使用:只要你试图使用原始类型的变量调用属性和方法的时候,自动包装
何时释放:方法调用完毕后,自动释放包装类型,又变成了原始类型

为什么null和undefined不能使用-因为前辈们没有为他们提供包装类型

扩展:

1.周期性定时器:每过一段时间就会自动执行一次
开启:timer=setInterval(function(){
    操作;
},间隔毫秒数)
停止:clearInterval(timer)

2.鼠标移入:onmouseover

3.鼠标移出:onmouseout

Day03

1.*****StringAPI:就是一些只有字符串可以使用的函数,不需要我们创建,直接使用

    1.转义字符串:\
    作用:1.将字符串中和程序冲突的字符转为原文
    "\"" '\"
    2.包含特殊功能的符号:
    换行:\n    制表符:\t->大空格,和tab按键一样
    3.*输出unicode编码的字符:
    \u4e00-ascii码:19968
    \u9fa5-ascii码:40869

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/arr.indexOf("关键字",starti);

从starti位置开始,查找右侧第一个关键字的第一个字符的位置

starti可以省略,默认从0位置开始查找

*返回值:找到了,返回第一个关键字的第一个字符的下标位置

没找到,返回-1,其实我们根本不关心下标为多少,我们只关心下标为不为-1

作用:判断有没有!

强调:数组也能使用此方法,数组这个方法是后期加上的,原本此方法只有字符串可用,老版本ie不支持

笔试题:默认只能获取到第一个关键字的下标,如何才能获取到所有关键字的下标?

    var str="no zuo no die no can no bibi no"
    
    varindex=-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.replace("固定关键字"/正则表达式,"新内容");

9.*******切割/分割/分隔字符串:

作用:将字符串转为数组:
var arr=str.split("自定义切割符");

注意:1.切割后,切割符就不存在了

2.如果你的切割符写的是"",切散每一个字符
   

10.去掉空白字符:str.trim/trimstart/trimEnd()

扩展:js如何创建元素:3步

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

2.为其设置必要的属性和时间:

 elm.属性名="属性值";
 elem.om事件名=function(){操作}
 

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

Day04

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

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

属性:Math有一些属性, 设计到科学计数法,但是几乎用不到,只有Math.PI有可能用到===3.1415926...这一串数字我们不需要自己创建,浏览器自带  

API:

1.取整:3种

1.上取整:超过一点点,就取下一个整数

var num=Math.ceil(num);//小数位数不能超过15位,否则此方法只能取整,不能上取整

2.下取整:无论超过多少,都会省略小数部分

var num=Math.floor(num);

3.四舍五入取整:

var num=Math.round(num);//只看小数位数的第一位

以上方法都是垃圾,都在取整,只能取整

//*num.toFixed(d);优点1.可以四舍五入,并且保留指定小数位数,d其实就是保留小数位数

2.解决浏览器自带的舍入误差,2-1.6=0.3999999这种情况就可以使用toFixed来解决
        
缺点:结果是一个字符串,建议搭配上parseFloat()使用

//笔试题:不允许使用toFixed的情况下,自己封装一个函数,由用户传入数字和保留位数,实现四舍五入操作:

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

2.乘方和开方:

*乘方:Math.pow(底数,幂);->更简化:底数**幂
开方:Math.sqrt(num);-仅仅只能开平方

3. *最大值和最小值:

    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

5.***随机数:Math.random();在0-1之间取一个随机的小数 搭配上parInt,只能取到0,但是不可能取到1,意味着娶不到最大值

    公式:parseInt(Math.random()*(max-min+1)=min)
    强调:只要以后网页中mou一块有随机的功能,他的底层一定是用到了随机数
    

2.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,dd,hh,mm,ss);//修改月份,从0~11,0代表1月
4.复制一个日期:
为什么:目前的所有API都是直接修改原日期的,无法获得修改之前的日期,所以,在执行API之前先进行复制,然后再操作复制后的日期
var end=Date(start);

使用:2类

1.两个日期对象之间,可以相减(大-小),得到一个毫秒差,换算出自己想要的任何一部分-日期的本质其实就是保存了一个毫秒数-做倒计时关键
创建日期的最后一种方式,绝对没人用:var date=new Date(毫秒数);//计算机元年:1970年1月1日8点整

2.API:

分量:时间的单位
年月日星期:FullYear Month Date Day
时分秒毫秒:Hours Minutes Seconds Milliseconds
每一个分量都有一对儿getxxx/setxxx的方法
其中getxxx负责获取一个分量的值
其中setxxx负责设置一个分量的值

特殊:
1.取值范围:

FullYear-当前年份的数字
Month-0~31
Date-1~31
Day-0~6:0代表是星期天,外国人的眼里星期天才是一周的开始
Hours-0~23
Minutes、Seconds:0~59
日期你知道了取值范围,如果你还故意设置拆除范围,他很聪明,会自动进制

2.Day 没有set方法

3.如果希望对某个分量进行加减操作:
date.setxxx(date.getxxx()+/-n)

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

3.定时器:

1.周期性定时器:每过一段时间就会执行一次,先等后做

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

2.一次性定时器:等待一段时间,只会做一次就结束

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

同步技术:代码必须一行一行的执行,前面没做完,后面就等着,定时器是我们第一次见到的异步技术:无论我这块代码多耗时,也不会卡住后续代码

Day05

1.BOM:Browser Object Model-浏览器对象模型:专门用于操作浏览器的,但是它使用的不多,远不如ES和DOM,浏览器很多操作都是自带的,而且BOM没有标准,各个浏览器都有自己的定义,但大部分都是一直的,除了老版的ie8

2.window对象:扮演者两个角色: 1.全局对象:保存着全局变量和全局函数

2.指代当前窗口本身:

属性:
1,获取浏览器的完整大小:outWidth/outerHight
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.事件:

 1window.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();