一、数组
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里面一切的东西都是对象,万物皆对象,除了undefined和null,【一切对象的底层都是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.为什么null和undefined不能使用. - 因为前辈们没有给他们提供包装类型
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()