JS第二章

116 阅读14分钟

一、数组

1.特点:线性排列,除了第一个元素外都有唯一一个前驱元素,除了最后一个元素,其他元素都有唯一一个后继元素。

2.创建数组的方式

(1)直接量方式 var arr=[]

(2)构造函数方式 var arr= new Array()

注     
(1)var arr=[num]; //创建了一个长度为1,值为num的数组
(2)new Array(num);//创建了一个长度为num的空数组,里面没有任何东西,只有无数的undefined

3.获取元素 arr[i]

4.添加/替换
arr[i]=值 ,当前位置无数据则是添加,有数据则是替换

5.数组的三大不限制

(1) 不限时元素

(2)不限制元素的长度

(3)不限制下标越界

6.数组的唯一属性length

(1) 向末尾添加元素: arr[arr.length]=新数据

(2)获取数组的倒数第n个元素:arr[arr.length-n]

(3)缩容:删除倒数第几个元素 arr.length-=n

7.遍历数组

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

8.JS组成

(1)ECMAScript ,ES语法

(2)DOM 文档对象模型

(3) BOM 浏览器对象模型

二、DOM (Document Object Model)文档对象模型

1.DOM根元素,将页面上所有元素、属性、文本、注释回视为一个DOM元素/节点/对象

2.查找元素

(1) 通过ID查找

 var elem = document.getElementById("id名")

(2)通过标签和类名查找

var elems=document/已经找到的某个父元素.getElementsByTagName("标签名");
var elems=document/已经找到的某个父元素.getElementsByClassName("类名");

注:
1、返回值,找到了返回的是一个类数组DOM集合,没找到返回空集合
2、*js只能直接操作DOM元素,不能直接操作DOM集合,解决:要么下标拿到某一个元素,要么遍历拿到每一个元素
3、不一定非要从document开始查找,如果从document去找,会找到所有的元素,可以换成我们已经找到的某个父元素

(3)通过 元素之间的关系 去查找元素:前提:至少要【先找到一个元素】才可以使用关系网:

1、父亲:elem.parentNode;//单个元素
2、儿子:elem.children;//集合
3、第一个儿子:elem.firstElementChild;//单个元素
4、最后一个儿子:elem.lastElementChild;//单个元素
5、前一个兄弟:elem.previousElementSibling;//单个元素
6、后一个兄弟:elem.nextElementSibling;//单个元素

3.操作元素

(1)内容:

 1.elem.innerHTML - 获取或设置开始标签到结束标签之间的内容【支持识别标签】
    获取:elem.innerHTML;
    设置:elem.innerHTML="新内容";

 2.elem.innerText - 获取或设置开始标签到结束标签之间的纯文本,【不支持识别标签】
    获取:elem.innerText;
    设置:elem.innerText="新内容";
    注1.2用于双标签
 3、input.value; - 专门获取/设置input的内容
    获取:input.value;
    设置:input.value="新内容";

(2)属性

1、获取属性值:elem.getAttribute("属性名");
2、设置属性值:elem.setAttribute("属性名","属性值");
简化版:
1、获取属性值:elem.属性名;
2、设置属性值:elem.属性名="属性值";
注:在使用简化版时
  (1)class必须写成className - ES2015(ES6)class变成了一个关键字
  (2)只能操作标准属性,不能操作自定义属性

(3)样式

1. css 三种样式
 *内联样式
  内部样式表 
  外部样式表 - 一阶段做开发用的都是外部样式表
  
  2.js来操作【内联样式】的好处:1、不会牵一发动全身
			      2、优先级最高
3.操作
   获取样式:elem.style.css属性名;
   设置样式:elem.style.css属性名="css属性值";

注意:(1)css属性名,有横线的地方,要去掉横线,变为小驼峰命名法
            background-color    --->    backgroundColor
            border-radius	--->	borderRadius
     (2)小缺陷:获取时,由于我们只学了操作内联样式,所以我们也只能获取到内联样式!

  

4.绑定事件:

elem.on事件名=function(){
	操作;	
		}
                
***关键字this - 这个,只能在【事件】内使用
        ·	如果单个元素绑定事件,this->这个元素
                如果多个元素绑定事件,this->当前触发事件的元素!!!

一、数组补充

面试题1:按值传递:可能会这么出题:var a=x;var b=a;修改a,b变不变,或者,修改b,a变不变?

(1)如果传递的是原始类型:其实是复制了一个副本给对方,两者互不影响

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

面试题2:如何释放一个引用类型呢?一定要看清楚有几个变量引用着这个引用类型,每个变量都要释放后才能释放干净

分析:在js底层有一个垃圾回收器,只有垃圾回收器的计数器(记录着这个数据有几个人引用着)为0的
时候才会删除不要的数据
建议:我们代码都要封装在一个函数内,函数中的一切变量都会自动释放!

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

索引数组:下标都是数字组成的数组,索引数组的下标无具体的意义,不便于查找

(1)创建hash数组并使用

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

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

(2)遍历hash数组

hash数组的length会失效,永远为0,所以必须使用for in循环 -不需要设置从哪里开始到哪里结束,
纯自动化的,专门为了遍历hash数组而存在的。
语法:
	for(var i in 数组名){
                //i -> 下标
                //数组名[i] -> 当前次元素
				}
    不止hash数组可以遍历,也可以遍历索引数组
    个人建议:索引数组依然使用for,hash数组在使用for in

(3)hash数组的原理:


(1)hash算法:将字符串,计算出一个尽量不重复的数字(地址值)符串内容相同,
             则计算出来的数字也一定是相同的
(2)添加元素:js解释器会将自定义下标交给hash算法,得到一个数字(地址值),
            直接将你要保存的数据放到此地址之中保存起来
(3)获取元素:js解释器会将指定的下标再次交给hash算法,得到一个和当初保存时完全一样的数字(地址值),
            通过此地址值就可以找到你当初保存的数据,取出来使用
            
  注:
  js里面一切的东西都是对象,万物皆对象,除了undefinednull,【一切对象的底层都是hash数组】


二、数组的API

1.arr 转 str

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

(1)将数组里面得内容拼接为一句话/单词 - 无缝拼接,其实就是拼接了一个空字符串
        var arr=["h","e","l","l","o"," ","w","o","r","l","d"];
        console.log(arr.join(""))

(2)***将数组拼接为DOM页面元素 - 数据渲染页面
        var arr=["-请选择-","北京","南京","西京","东京","重庆"];
        var str="<开始>"+arr.join("</结束><开始>")+"</结束>";
        sel.innerHTML=str;

2.拼接数组:添加元素的新方式,将传入的实参全部拼接到arr的末尾

var newArr=arr.concat(新值1,arr1,...);

注:
(1)不修改原数组,只会返回一个新数组
(2)concat支持传入数组参数,悄悄的将你传入的数组打散为单个元素再拼接

3.截取子数组:只想取出数组中的某一个部分,根据传入的开始下标一直截取到结束下标

var subArr=arr.slice(start,end);

1、不修改原数组,只会返回一个新数组
2、含头不含尾
3、end可以省略不写,如果省略不写,则从start位置一直截取到末尾
4、start和end都可以省略不写,那么从头到尾完整的复制一份,此操作也叫做深拷贝!复制了一个副本给对方,两者互不影响。
5、支持负数参数,-1代表倒数第1

以上的API都是不会修改原数组的,只会返回新东西

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

1.删插替:.splice();

(1)删除:var dels=arr.splice(starti,n);//n代表删除的个数
注:虽然他直接修改原数组,但是也有返回值,返回的是被删除的数据组成的一个新数组,
    没有删除也会返回一个空数组
    
(2)插入:var dels=arr.splice(starti,0,新值1,...);
  注:
    1、原starti位置的元素以及后续元素都会向后移动
    2、尽量的不要插入一个数组,会导致我们的数组一些是一维,一些是二维,遍历的时候极不方便
    
(3)替换:var dels=arr.splice(starti,n,新值1,...);
         注:删除的个数和插入的个数不必相同

2.翻转数组:arr.reverse();

3.数组排序 arr.sort()

(1)手写冒泡排序:前一个元素和后一个元素进行对比,如果前一个>后一个,两者就要交换位置,
			var arr=[12,3,25,4,7,687,6,354,534,8,62,33,4];
			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){
		console.log(a);//后一个数
		console.log(b);//前一个数
                return a-b;    
	   
		});
       (1)function(a,b){}此函数叫做匿名回调函数,会自动调用
       (2)sort方法会根据你返回的结果为正数、负数、0自动考虑要不要交换位置
       (3)希望按照数字降序排列  return b-a;
	   
           
           
  补:1、以后只要网页上有排序功能,说明他的底层一定是一个数组,因为js之中只有数组可以排序
      2、以后只要网页上有随即功能,说明他的底层一定用到了随机数公式



4.栈和队列:添加元素和删除元素的新方式 (1)栈:有一端被封闭的数组,只能从另一端进出

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

1.开头进:arr.unshift(新值,...);
添加元素的新方式,向前添加:缺点:导致其他元素的下标都会发生变化

2.开头出:var first=arr.shift();
删除元素的新方式缺点,向前删除,一次只会删除一个,也有返回值,返回的就是被删除的元素:导致其他元素的下标都会发生变化

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

4.结尾出:var last=arr.pop()
删除元素的新方式缺点,向后删除,一次只会删除一个,也有返回值,返回的就是被删除的元素


三、扩展

1.二级联动

(1)select专属事件:onchange()   在选项卡发生变化时才会触发
(2)select专属属性:SelectedIndex    获取到选中项的下标,其他标签只能用自定义下标
(3)必须使用二维数组,细分分类

2.二维数组

(1)创建:var arr =[[值1,值2,...],[值1,值2,...],[值1,值2,...],...]

(2)访问

(3)遍历:两成循环,外层控制行,内层控制列

  for(var r=0;r<arr.length;r++){
     for(var c=0;r<arr[r].length;c++){
         arr[r][c]
    }
  }
  
  
  面试题:列下标越界返回undefined
         行下标越界会报错

四、字符串String

1.String的概念:

(1)什么是字符串:多个字符组成的【只读】字符【数组】

只读:字符串的API都不会修改原字符串,只会返回一个新字符串
 1、和数组有相同点:
    (1)字符串中的个数:str.length
    (2)获取字符串中的某个字符:str[i]
    (3)遍历字符串
    (4)所有数组不修改原数组的API,字符串也可以使用(concat、slice)
 2、和数组的不同点:
     (1) 所有数组的直接修改原数组的API,字符串都不可以使用


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

*String Number Boolean -> 包装类型
*Array *Function Date(日期) Math(数学) *RegExp(正则:验证)
Error(错误)
*Object(面向对象)
Global(全局对象) - 在浏览器端被window对象给代替了,保存着全局变量和全局函数,window可以省略不写,
在后端语言node.js中全局对象就叫做global

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

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

3.StringAPI:只有字符串可以使用的函数,不需创建,直接使用

(1)转义字符:\

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


(2)大小写转换:将字符串中的每个英文字符统一的转为大写 或 小写

1.何时使用(验证码):只要程序不区分大小写,就要【先统一】的转为大写 或 小写
2.如何使用:
    var 大写=str.toUpperCase();
    var 小写=str.toLowerCase();


(3)获取字符串中的指定位置的字符:str.charAt(i) === str[i];

(4)获取字符串中的指定位置的字符的ascii码

1.获取字符串中的指定位置的字符的ascii码
 var ascii=str.charCodeAt(i);

 2.通过ascii码转回原文:
  var 字=String.fromCharCode(ascii码);

(5)检索字符串:检查索引 - 检查下标,获取关键字的下标

var i=str.indexOf("关键字",starti);
    1.从starti位置开始,查找右侧第一个关键字的第一个字符的位置
    2.starti可以省略,默认从0位置开始查找的
    3.返回值:找到了,返回的第一个关键字的第一个字符的下标位置
	     *没找到,返回-1,其实我们根本不关心下标为多少,我们只关心下标为不为-1
    4.作用:判断有没有
    
 强调:数组也能使用此方法,数组这个方法其实是后期才添加上的,原本此方法只有字符串可用,比如老IE的数组就没有此方法
 
  笔试题:默认只能获取第一个关键字的下标,如何才能获取到所有的关键字的下标呢?
            var str="no zuo no die no can no bibi";
            var index=-1;
            while((index=str.indexOf("no",index+1))!=-1){
                    console.log("找到了关键字,下标为:"+index);
            }

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

(7)截取字符串:3个

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

(8)替换字符串:搭配正则非常的强大

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

(9)切割/分割/分隔字符串:

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

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