js第二周笔记

123 阅读17分钟

day 01

一、数组的基础(填坑)

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的时候才会删除不要的数据。
建议:我们的代码都要封装为一个函数,函数中的一切变量都会自动释放
索引数组:下标都是数字组成的数组。

二、hash数组(关联数组):

下标是可以自定义的
为什么:索引数组的下标无具体的意义,不便于查找。
如何使用:
    1.创建:2步
    (1)创建空数组:var arr=[];
     (2)为数组添加自定义下标并且赋值:arr["自定义下标"]=新值;
     2.访问元素:arr["自定义下标"]3.强调:hash数组的length失效了,永远为0!
         遍历hash数组:不能再使用for循环,必须使用for in 循环- 其实for in并不应该称之为一个循环,因为它不需要设置从那儿开始到哪儿结束,专门为了遍历数组存在的。
        for(var i in 数组名){
        i;//下标
        数组名【i】;//当前次元素
                }
        不止能遍历hash数组,也能遍历索引数组
        个人建议:索引数组依然是for,hash数组再使用for in。
      4.hash数组的原理:
          hash算法:将字符串:,计算出一个尽量不重复的数字(地址值)
                  字符串内容相同,则计算出来的数字也一定是相同的
           添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将你要保存的数据放到此地址保存起来。
            获取元素:将制定的自定义下标交给hash算法,得到一个和当初保存时一样的数字(地址值),通过此地址找到你当初保存的数据,取出来使用。
      5.js里面一切的东西都是对象,万物皆对象,除了undefined和null【一切对象的底层都是hash数组】
      学习这一块最大的目的:是为了对象做准备工作

三、数组的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 del =arr.spice(starti,n) /n代表删除个数
 特殊:虽然它直接修改原数组,但是也有返回值,返回的是被删除的数据组成的一个新数组,因为前辈考虑到有 可能删除的东西正好是需要的东西,哪怕什么都没删除,也会返回一个空数组
 插入:arr.splice(starti.0,新值,。。。);  
 特殊
1.原starti位置的元素以及后续元素都会向后移动
2.尽量的不要插入数组,会导致我们的数据一些事以为的,一些事而为,遍历的时候非常不方便
  替换:var del=arr.splice(starit,n,新值,。。。);
  特殊:删除的个数和插入的个数不必相同

5.翻转数组:

 arr.reverse();今日一见见不到了

6.数组排序:

(1)笔试时

冒泡排序:前一个元素和后一个元素进行对比,如果前一个>后一个,两者就交换位置,但是昨晚一轮发现只有最大的数字到了最后,所以再开循环反复使用,固定公式:
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);

(2)正式开始时候: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:希望数字降序排列
     强调:
     切记:  1、以后只要网页上有功能带有排序,他的底层一定是数组,因为js中只有数组可以排序
            2、以后只要网页上有随机的功能,那么他的底层一定用到了随机数公式

day 02

一、数组的api

1.栈和队列

添加元素和删除元素的新方式:
栈:其实就是数组,只不过一段封闭了,只能从另一端进出
何时使用:现实生活中,情况不多:电梯、旅游巴士。。。优先使用最新的数据
如何使用:
    开头进:arr.unshift(新值,。。。);//添加元素的新方式,向前添加,缺点:导致其余元素的下标都发生变化
    开头出:var first=arr.shiift();//删除元素的新方式,向前删除,一次只能删除一个,缺点:导致其余元素的下标都发生变化
    结尾进:arr.push(新值,。。。);//添加元素的新方式,向后添加。
    结尾出:var last=arr.pop();//删除元素的新方式,向后添加。
    
 队列:其实就是数组,只不过一端进,从另一端出:
     开头进:arr.unshift(新值,。。。);
     结尾出:var first=arr.shift();

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

何时使用:在一个数组,希望再次细分每个分类
创建:
    var arr=[
            ["",,],
            ["",,],
            ["",,]
    ]
访问:arr[行下标][列下标]
特殊:列下标越界,返回nuderfined
    行下标越界,得到的是一个报错,因为行下标越界已经的得到一个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还提供了3组6个API:

1.判断(2个)

(1)every

每一个,要求所有元素都满足条件才会为true,只要有一个不满足则为false,非常类似于我们的&&
    var bool = arr.every(function(val.arr){
        //var -当前的值
        //i -当前的值的下标
        //arr - 当前数组本身
        return 判断条件;   
    })

(2)some

有一些,要求只要有一个元素都满足条件会为true,所有元素都不满足则为false,非常类似于我们的||
    var bool=arr.some(function(val,i,arr){
        return 判断条件;
    })

2.遍历

拿到数组中的每个元素做相同或相似的操作
forEach(function(function(val,i,arr){
    return 直接做你想要的操作;
})

3、过滤和汇总

(1)过滤

筛选出你需要的部分,但是和现实不一样的是原数组并不会发生变化
    var subArr=ar.filter(function(val,i,arr){
    return 判断条件;
    })

(2)汇总

var result=arr.reduce(function(prey,i,arr){
    return prev+val;
},基础值)

以上6个API 都是在简化我们的for循环操作,以后数组我们kennel真的不会再写for循环

es6肩头函数:简化一切匿名回调函数的

固定公式:function去掉,()和{}之间添加=>,如果形参只有一个,那么()可以省略,如果函数体质优一句话,那么{}也可以省略,如果函数题只有一句话并且是retrn,那么return和{}都可以省略

day 03

一、string的概念

1.什么是字符串:

    多个字符组成的【只读】字符【数组】

2.和数组有相同点:

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

3.和数组的不同点

所有数组的直接修改原数组的API,字符串都不可以使用,比如排序只有数组可以使用,但是
字符串也有很多很多属于自己的API

4.引用/对象类型:11个

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

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

为什么:原始类型的值原本就是没有任何属性和方法,意味着原始类型本身是不支持.去做任何操作的
但是前辈们发现字符串经常会被我们程序员所操作,为了方便我们程序员将这三个人提供了包装类型(提供了属性和方法)
何时使用:
只要你试图使用原始类型的变量调用属性或方法的时候,自动包装
何时释放:
方法调用完毕后,自动释放包装类型,又变成了原始类型
为什么nullundefined不能使用. - 因为前辈们没有给他们俩提供包装类型

----------------------------------------------------------------------

二、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("关键字“,strti);
从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.replace("固定关键字"/正则表达式,"新内容");

9、切割/分割/分隔字符串:

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

注意:

1、切割后,切割符就不存在了
2、如果你的切割符写的是"",切散每一个字符   

10.去掉空白符

var,trim/trimStart/trimEnd();

扩展:JS如何创建元素(3步):

1、创建空标签:var elem=document.createElement("标签名");
2、为其设置必要的属性和事件:
	elem.属性名="属性值";
	elem.on事件名=function(){操作}
3、挂载上树/渲染页面:父元素.appendChild(elem); 

day 04

一、Math对象

专门提供了数学计算的API
强调:
不需要创建,直接使用
属性:Math有一些属性,涉及到科学记数法,但是几乎用不到,只有Math.pi有可能用到===3.141596这一串数字我们不需要穿件,浏览器自带。

1.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.解决浏览器带来的舍入误差
缺点:结果是一个字符串,建议搭配上parseFloat()使用

笔试题

不允许使用toFixed的情况下,自己封装一个函数,由用户传入数字和保留位数,实现四舍五入操作:
 var a =  toFixed(Math.PI,3);
  function toFixed(num, d) {
    num *= (10 ** d);
    num = Math.round(num);
        num /= 10 ** d;
    return num;
  }
  console.log(a);

(2)乘方和开方

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

(3)最大值和最小值

var max/min=Math.max/min(a,b,c,d....);//自动在你传入的数字中比较出最大或者最小值。
问题:本身不支持数组参数
解决:固定用法:Math.max/min.apply(Math,arr);//apply具有☔️数组的功能

(4)绝对值:把负值转为正数

Math.abs(-1); //1

(5)随机数:Math.random();在0-1之间去一个随机的小数

搭配上parseInt,只能取到0,但是不可能取到1,意味着取不到最大值。
公式:parseInt(Math.random()*(max-min+1)+min)
强调:只要以后网页中某一块有随机的功能,他的底层一定用到了随机数

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=new 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~11
Date - 1~31
Day - 0~60代表是星期天,外国人的眼里星期天才是一周的第一天的				Hours - 0~23
Minutes、Seconds:0~59
日期你知道了取值范围,如果你还故意设置超出范围,他很聪明,会自动进制
2、Day,没有set方法
3、如果希望对某个分量进行加减操作
date.setXXX(date.getXXX()+/-n)
4、格式化日期为本地字符串:
date.toLocaleString(); - 垃圾:具有兼容性问题,我们一般会选择自己创建一个格式化方法来格式日期
用了此方法会失去一些东西:日期的自动进制、日期的API
但是你也会获得一些东西:字符串的API

3、定时器:

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

开启:timer=setInterval(callback,间隔毫秒数);
停止:clearInterval(timer);
(2)一次性定时器:等待一段时间,只会做一次就结束了
开启:timer=setTimeout(callback,间隔毫秒数);
停止:clearTimeout(timer);

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

day 05

一、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>
JSopen("url","_self");

2、当前窗口打开,禁止后退:使用场景:

比如电商网站,结账后不允许后退
HTML做不到了,只有JS可以,也不是window能做到的,而是另外一个人historyhistory:当前【窗口的历史记录】,他其实可以做的事儿就是前进后退
location:当前【窗口正在打开的url】,有一个API:location.replace("新url");
location.replace("新url");//叫做替换,不叫做跳转,不会产生历史记录,自然也不能后退了,但是网址替换了,网页必然会发生变化

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

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

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

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

学完这块,我们知道:

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>图片和txt</a>

(2) 打开新窗口/新链接:

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

特殊:

1、如果没有加第三个参数,那么窗口会和浏览器融为一体	
2、如果你加了第三个参数,那么窗口会脱离浏览器独立存在

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

(4)改变新窗口的大小:

newW.resizeTo(新宽,新高);

(5)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();