js第二周学习笔记—一些常用API

108 阅读20分钟

js第二周学习

day1数组及API

1、数组的创建

1、创建数据组(两种方式)

  1、直接量方式:

var arr=[值1,值2,...];

  2、构造函数:

var arr=new Array(值1,值2,...);

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

2、面试题:按值传递

var a=x;var b=a;//修改a时,b不变;或修改ba不变。

   如果传递的是原始类型:其实就是复制了一个副本给对方,两者互不影响
   如果传递的是引用类型:因为引用类型很大,不可能保存在本地变量中,只能保存在一个地址中,传递的过程其实就是赋值了自己的地址给对方两者用着同一个地址,一个修改了另一个也会跟着变化。本质上只是将自己的地址给对方一起使用,也叫作浅拷贝
    深拷贝从头到尾复制给对方一份,两者的地址不同互不影响

3、如何释放一个引用类型:

  一定要看清楚有几个变量引用着这个引用类型,每个变量都要释放后才算释放干净了。
     在js底层有一个垃圾回收器,只有垃圾回收器的计数器(这个计数器记录着有多少变量在引用着这个引用类型)为0时才会删除不要的数据。
     建议:我们的代码都要封装在一个函数中,在函数中一切变量都会自动释放。
     索引数组:下标都是数字组成的数组。

4、哈希数组

 含义:下表是可以自定义的数组
 为什么:索引的下标无具体意义,不便于查找
 如何使用:
  1、创建:
   1、创建空数组:

var arr=[];

   2、为数组添加自定义下标并赋值

arr["自定义下标"]=新值;

  2、访问元素:

arr["自定义下标"];

   3、强调:哈希数组的长度失效永远为0
    遍历哈希数组:不能再使用for循环,必须用for in 循环,因为它不用设置变量从哪里开始到哪里结束。纯自动换的,准门为了遍历哈希数组存在的

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

    此方法不仅能遍历哈希数组,也能遍历索引数组。
    个人建议:所以数组依旧使用for循环去遍历,哈希数组才是用for in循环去遍历。
   4、哈希数组的原理:
    hash算法将字符串计算出一个尽量不重复的数字(地址值);
     字符串的内容相同,则计算出的数字也相同。
    添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将要保存的数据放到此地址中保存起来。

arr["自定义下标"]=新值;

    获取元素:将指定的下标交给hash算法,得到一个和保存时一样的数字(地址值),通过此地址值找到当初保存的数据,取出来使用
   5、js中一切都是对象,万物皆是对象,除了undefined和null[一切对象的底层都是hash数组],学习hash数组是为了对象做准备。

5、数组的API

   含义:前辈们预定义了很多的方法,等待我们去学习,我们程序员只需要学会如何使用就可以直接去使用——以下的方法只有数组能够使用。

1、数组转字符串:

var str=arr.join("自定义连接字符");//如果引号里为空此方法无效

    固定套路(两个):
     1、笔试题:将数组的内容拼接成一句话/单词,无缝拼接,其实就是拼接了一个空字符串。

var arr=["h","e","l","l","o"];
var str=arr.jion(" ");<br>

     2、将数组拼接成DOM页面元素——数据渲染页面

1、取数据:
var arr=["--请选择--","数据1","数据2","数据3"];
2、将数组拼接成页面标签字符串:
var str="<option>"+arr.join("</option><option>")+"</option>";
3、将数据写入标签:
sel.innerHTML=str;

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

    将传入的实参全部拼接到数组末尾

var newArr=arr.concat(新值1,新值2,...(数组也是可以的,拼接以后会被打散成单个元素))

    特殊:
     1、此方法不改变原数组,只会返回一个新数组,需要定义一个数组来接住它;
     2、concat方法支持传入数组参数,并且悄悄地将传入的数组打散成功单个元素再进行拼接。

3、截取子数组:

    根据传入的开始下标截取到结束下标加1;

  var subArr=arr.slice(开始下标,结束下标+1);

    特殊:
     1、不修改原数组,返回一个新数组,也是要接住它。
     2、含头不含尾,正是如此结束下标才要加1;
     3、结束下标可以省略不写,如果省略了,会从下标开始的位置一直截取到末尾的最后一个元素。
     4、开始下标也可以省略,如果两个实参都省略了,那么会从头到尾的完全复制一份给对方。从头到尾复制一份给对方叫做深拷贝(两者地址不同,互不影响)
     5、支持负数参数,-1代表倒数第一个。
**以上的三个数组的API都是不会直接修改原数组的,后面学习的数组的API都是直接修改原数组的

4、删插替

    1、删除:

arr.splice(开始下标,删除个数);

     删除的内容会返回一个新数组,可以接住方便后期使用。哪怕没有进行删除也会返回一个新数组
    2、插入:

arr.splice(开始下标,0,新值);

     特殊:
      1、原来在此位置上的元素的下标会变为 原下标+插入个数 后续的元素下标也是如此。我们新插入的第一个元素顶替了原来在这个位置上的元素。
      2、尽量不要插入数组,因为插入了数组以后导致我们的数组中有一维的也有二维的,遍历起来很麻烦。
    3、替换:

arr.splice(开始下标,删除个数,新值.....);

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

5、反转数组:

arr.reserve();

6、数组排序:

    1、笔试题:冒泡排序:前一个元素和后一个元素作比较,如果前一个元素大于后一个元素,那么两者交换位置,但是一轮比较下来之后最大的一个元素往后放了,所以要再开一个循环反复进行此操作:

for(var i=0;i<arr.length;i++){
    for(var j=0;j<arr.length-i;j++){
        if(arr[j]>arr[j+1]){
            var m=arr[j];
            arr[j]=arr[j+1];
            arr[j+1]=m;
            }
        }
    }
console.log(arr);

    2、正式开发时我们是用数组排序API:

arr.sort();

     默认:将数组的元素转换为字符串以后按位PK,并进行排序。
     带来了一个问题,怎么才能让它按数字大小排列:
     解决:

arr.sort((a,b)=>a-b);

     a-b返回是正数说明后一个比前一个大,负数前一个比后一个大,返回0则两者相同
     sort()会自动根据返回的结果考虑换不换位。
     降序排列:

arr.sprt((a,b)=>b-a);

    强调
     1、切记以后页面上有排序功能,那么它的底层一定是数组,因为在js中只有数组有排序功能。
     2、以后只要页面上有随机功能,那么底层用的一定是随机数函数。

day2数组的API续

1、栈和队列:添加元素和删除元素的新形式

 栈:其实就是数组,一段封闭,只能从一端进出
  如何使用:
   开头进:添加的元素放在开头第一个(缺点:改变后续元素的下标)
   开头出:每次都只能删除开头第一个,并且不改变原数组,要用新变量接住

    开头进:
    arr.unshift(新值...);
    开头出:
    arr.shift();

   结尾进:添加的元素接在尾部
   开头出:每次都只能删除最后一个,并且不改变原数组,要用新变量接住

    结尾进:
    arr.push(新值...);
    结尾出:
    arr.pop();

 队列:其实就是数组,只不过是一端进另一端出
  用法:实际上就是栈的用法混合着用。

      开头进:
    arr.unshift(新值...);
      结尾出:
    arr.pop();
    
    
      结尾进:
    arr.push(新值...);
      开头出:
    arr.shift();

2、二维数组:

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

var arr=[[1,2,3...],
[2,3,4...],
["","",""...],
...
]

 访问:

arr[r][c];

 特殊:
 列下标c越界返回undefined
 行下标r越界会报错
 遍历二维数组:必然是用两层循环,外层控制行,内层控制列

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

3、ES6还提供了3组6个API

 1、判断(2个):
  every:每一个:arr.every()要求所有的元素都要满足才能返回true,但凡有一个条件不满足返回的都为false

    var bool=arr.every(function(val,i,arr){
        return 判断条件:
    })

  some:arr.some()有一个条件满足就为true,所有条件都不满足返回false;

var bool=arr.some(function(val,i,arr){
        return 判断条件:
    })

 2、遍历(2个):循环拿到数组里的每一个元素做相同或类似的操作
  forEach();直接修改原数组

arr.forEach(function(val,i,arr){
        操作;
    })

  Map();不修改原数组,而是返回一个新值

var newArr=arr.some(function(val,i,arr){
        return 操作:
    })

 3、过滤和汇总
  过滤:arr.filter()筛选出需要的部分,原数组不发生改变

 var newArr=arr.filter(function(val,i,arr){
        return 操作:
    })

  汇总:arr.reduce()

 var newArr=arr.reduce(function(pre,val,i,arr){
        return pre+val:
    },基础值)

以上的六个API都是在简化我们的for循环操作,以后数组我们可以不用for循环遍历了

4、箭头函数:简化一切匿名回调函数

一个形参一句话:形参=>操作语句;
多个形参一句话:(形参1,形参2...)=>操作语句;
多个形参多句话:(形参1,形参2...)=>{
                    语句1;
                    语句2;
                    ...
                }    

5、引用对象11个

String Number Boolean——包装类型
Array Function Date(日期) Math(数学) RegExp(正则) Error(错误)
Object(面向对象开发方式)
 Global(全局对象):在浏览器端被window对象代替,自然保存着全局变量和全局函数,只不过window对象可以不用写,等后期学了node.js这个后端语言后,在node.js中全局对象就叫做Global。
包装类型:专门用于原始类型的值封装为一个引用类型对象的
  为什么要有包装类型:原始数据类型的值没有任何的属性和方法,意味着原始数据类型本身是不支持使用属性和方法的,但是由于程序员经常使用String,Number,Boolean这三个类型,所以后期给这三个类型提供了包装类型(提供了属性和方法)
   何时使用包装类型:只要你试图使用原始数据类型的变量调用属性和方法时,自动包装
   何时释放:方法调用完成后,自动释放包装类型,变为原始类型
   为什么null和undefined不能使用:因为前辈们没有给它两提供包装类型

day3字符串String

String的概念

 什么是字符串:多个字符拼接组成的只读字符数组(只读:不改变原有的字符串,返回一个新的字符串)
 和数组有相同点:
  1、字符串中的个数:str.length;
  2、获取字符串的某个字符:str[i];
  3、遍历字符串:for循环;
  4、所有数组API中不会修改原数组的API,字符串也可以使用(concat,slice);
 和数组不同的地方:
  所有数组修改原数组的API字符串都不可以使用,比如排序只有数组可以使用,但是字符串不能使用

StringAPI:

1、概念:就是只有字符串才可以使用的函数。

2、转义字符:\

 作用:
  1、将字符串中和程序冲突的字符转为原文""" '''
  2、包含特殊功能的符号:
   换行:\n
   制表符:\t 和Tab的效果一样

3、输出Unicode编码的字符

 \u4e00-ascii码:19968;
 \u9fa5-ascii码:40869;

4、大小写转换:整体转换?

大写:var upper=str.toUpperCase();
小写:var upper=str.toLowerCase();

5、获取字符串中指定位置的字符:

str.charAt(i)===str[i];

6、获取字符串中指定位置字符的ASCII码:str.charCodeAt(i);

var ascii=str.CharCode(i);

  过ascii码转为原文:String.fromCharCode(ascii)

7、检索字符串:str.indexOf("关键字",开始下标i);

 检查索引,检查下标;获取关键字的下标

var i=str/arr.indexOf("关键字",开始下标i);

 从开始下标位置开始,查找右侧的第一个关键字的第一个字符的位置,开始下标可以省略,默认从0位置开始查找。
它的返回值
  找到了返回第一个关键字的下标位置
  没找到返回-1,实际开发过程中不必担心返回的是什么,关心的就是返回的是不是-1
 作用:判断有没有!
 强调:数组也能使用此方法
笔试题:默认只能获取第一个关键字的下标,怎么才能获取到所有的关键字的下标呢?

var str="no zuo no die no can no bb";
var index=-1;
while((index=str.indexOf("no",index))!=-1){
    console.log("找到了,下标为:"+index);
}

8、拼接字符串:var newStr=str.concat("新字符串"...);作用还不如+运算

9、***截取字符串(3种):常用slice(开始下标,结束下标+1);用法和数组完全一致

var subStr=str/arr.slice(开始下标,结束下标+1);
str.substring(开始下标,结束下标+1)//此方法不支持负参数
str.Str(开始下标,截取个数);

10、***替换字符串:var newStr=str.replace("固定关键字"/正则表达式,"新字符串")很强大,后期深入学习

var newStr=str.replace("固定关键字"/正则表达式,"新字符串");

11、*****切割/分割/分隔字符串str.sblice("自定义切割符");

 作用:将字符串转换为数组:

var newArr = str.sblice("自定义切割符");

 注意:
  1、切割后,切割符就不存在了
  2、如果紫萼各付写的是"",则是切散每一个字符

12、去掉空白字符:str.trim()/trimStart/trimEnd();

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

 1、创建空标签:

elem=document.creatElement("标签名");

 2、为其设置必要的属性和事件:

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

 3、挂载回界面:父元素.appendChild(elem);

day4、Math和Date

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

 强调:不需要创建,直接使用
 属性:Math有一些属性,涉及到科学计数法,但是几乎不用,只有Math.PI有可能用到,这一串的圆周率数字我们不需要自己创建,浏览器自带

2、API

1、取整:

1、上取整:Math.ceil(num);超过一点点就取之后的一个整数
var num=Math.ceil(num);//小数位数不得超过15位,否则此方式失效
2、下取整:Math.floor(num);不管超过多少都会省略小数部分
var num=Math.floor(num);
3、四舍五入取整:Math.round(num);只看小数位数的第一位
var num=Math.round(num);

 以上三个取整的方法都是垃圾:只是在取整,也只能取整
 总的取整的方法:以上三个+parseInt(str去掉单位)+num.toFixed(d)
  num.toFixed(d)的优点:
   1、可以四舍五入,并且保留指定小数位数,d就是保留的小数位数
   2、解决浏览器自带的舍入误差
  num.toFixed(d)的缺点:结果是一个字符串,建议搭配上parseFloat();使用
  笔试题:不允许使用toFixed的情况下,自己封装一个函数,由用户传入数字和保留位数,实现四舍五入操作:

 function 函数名(num,d){
     num*=(10**d);
     num=Math.round()num;
     num/=(10**d);
     return num;
 }
 使用toFixed的情况:
 var result=toFixed(Math.PI,d);
 console.log(result);

2、乘方和开方:

1、乘方:Math.pow(底数,幂);-->更简化:底数**幂
var newNum = Math.pow(num,d);
2、开方:Math.sqrt(num)---仅仅只能开平方
var newNum = Math.sqrt(num);

3、最大值和最小值

1、最大值:Math.max(a,b,c,d....);
var max=Math.max(a,b,c,d....);
2、最小值:Math.min(a,b,c,d....);
var min=Math.min(a,b,c,d....);

 以上两种方法本来不支持数组的,但是有数组的固定用法:

var max/min = Math.max/min.apply(Math,arr);//apply具有打散数组的功能

4、绝对值:Math.abs(-1);把负数转换为正数;

Math.abs(-1);

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

 搭配上parseInt()只能取到0;
 公式:ParseInt(Math.random()*(最大值-最小值+1)+最小值);
 强调:以后在页面上有随机功能它的底层一定是个随机数

2、Date对象:日期对象,提供了操作日期和时间的API

1、创建:4种

1、创建一个当前日期:new Date();
var now=new Date();
2、创建一个自定义时间:new Date("yyyy/MM/dd hh:mm:ss");
varbirth=new Date("yyyy/MM/dd hh:mm:ss");
3、创建一个自定义时间:new Date(yyyy,MM,dd,hh,mm,ss);此方法得修改月份,因为代码中月份从0开始
4、复制一个日期:var end=new Date(start);
var start=new Date();
var end=new Date(start);

 为什么要复制日期:日期的所有API都是直接修改原日期的,无法获得修改之前的时间,所以在执行API之前先得复制,然后再对复制后的日期进行操作
 使用:2类
  1、两个日期对象之间,可以相加减(大-小),得到一个毫秒差,可以根据毫米差换算出自己想要的任何一部分时间——日期的本质上就是保存了一个毫秒数,这也是做倒计时的关键

2、API

1、分量:时间的单位

 年: FullYear
 月: Month
 日:Date
 星期:Day
 时:Hours
 分:Minutes
 秒:Seconds
  以上的每个分量都有一对getXXX/setXXX的方法,其中getXXX负责获取一个分量的值,setXXX是设置一个分量的值(星期 Day不能设置)
  特殊:
   1、取值范围:(如果设置超过取值范围会自动进制)
    FullYear:当前年份的数字
    Month:0~11
    Date:1~31
    Day:0~6(0代表星期天)
    Hours:0~23
    Minutes:0~59
    Seconds:0~59
   2、如果希望对某个分量进行加减操作:

  var date=new Date();
  date.setXXX(date.getXXX() +/- n);

   3、格式化日期为本地字符串:
    date.toLocaleString();垃圾的原因:具有兼容的问题,我们一般会选择自己创建一个格式化的方法来格式日期。并且用了此方法会失去一些东西:日期的自动进制、日期的API,但同时也会获得一些东西:字符串的API

3、定时器

1、周期性定时器:setInterval(callback,间隔毫秒数),每过一段时间就执行一次,先等后做
开启:timer=setInterval(function(){操作},间隔毫秒数);
关闭:clearInterval(timer);
1、一次性定时器:setTimeout(callback,间隔毫秒数),等待一段时间,只做一次就就结束了
  开启:timer=setTimeout(function(){操作},间隔毫秒数);
  关闭:clearTimeout(timer);

day5 BOM

1、BOM:Browser Object Model——浏览器对象模型

 含义:专门用来操作浏览器的,但是它的使用不多,远不如ES和DOM,浏览器的很多操作都是自带的,而且BOM也没有标准,各个浏览器都有自己的定义,但大部分浏览器都是一只规范的(老IE除外)

2、window对象:扮演着两个角色:

 1、全局对象:保存着全局对象和全局函数
 2、只带当前窗口本身

1、window属性:

1、获取浏览器的完整大小:
outerWidth/outerHeight
2、获取浏览器的文档显示区域的大小
innerWidth/innerHeight;//电脑不同大小也不同
3、获取屏幕的完整大小:跟window没关系
screen.width/height;//用于桌面应用

2、window方法:

1、打开新链接的新方式:

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

open("url","_self");

 2、当前窗口打开,禁止后退:不是window做的而是location做的

 location.replace("新url");//不会产生历史记录,自然就不能后退,网址变化网页自然变化

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

open("url","_blank");

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

open("url","自定义一个name");//其实窗口的底层是有一个名字的,如果打开了一个已经打开着的名字的窗口,它会将其关闭再次打开

拓展:  1、下载按钮:<a href="xxx.zip/exe/rar/7z">下载
 2、打开图片和文本:<a href="xxx.png/jpg/jpeg/txt">打开
 3、直接书写JS——不需要绑定点击事件:<a href="JavaScript:js代码">操作

2、打开新链接/新链接:
newW=open("url","target","width=?,height=?,left=?,right=?");

 特殊:
  1、如果没写第三个参数,name窗口会和浏览器融为一体
  2、如果加了第三个参数,那么窗口会脱离浏览器独立存在
  3、改变新窗口的位置:newW.moveTo(新X,新Y);
 4、window提供了三个框:
  1、警告框:alert("警告文字");
  2、输入框:var user=prompt("提示文字");
  3、确认框:var bool=confirm("提示文字");
定时器也是window的

3、window事件:

1、window.onload事件——加载事件:等待其他所有的资源加载完毕后才会执行的代码,放在里面的代码最后才执行

2、window.onresize事件——窗口如果大小发生改变就会触发,搭配上判断

3、innerWidth可以理解为js版本的css媒体查询

4、window.onscroll事件——滚动事件,页面一旦滚动就会触发

1、获取滚动条的位置:window.scrollY
2、获取元素距离页面的顶部和左边的距离:elem.offsetTop/offsetLeft

5、本地/客户端 存储技术:

1、cookie:淘汰了,存储的大小只有2kb,而且操作极为麻烦,存储时效只有30天
2、webStorage:H5带来了一个新特性,存储的大小8mb,永久保存,而且非常简单分为两种:

 1、sessionStorage——会话级,只要浏览器关闭数据就死亡
 2、localStorage——本地级,只要你不清空,就会永久存在
 两者的用法是一模一样的,不用创建,直接可用
 操作:
  1、添加:xxxStorage.属性名="属性值";
  2、读取:xxxStorage.属性名;
  3、删除:xxxStorage.removeItem("属性名");
  4、清空:xxxStorage.clear();