数据类型转换
- 转数值
- Number(需要转化的对象) 所有数据类型都可以转换,完全等效于隐式转换
- parseInt(需要转化的对象) 字符串和小数转为整数型数字,从左向右依次读取每个字符,碰到非数字字符,就停止转换,如果一来就碰到了不认识的,则为NaN
- parseFloat(需要转化的对象) 执行原理同parseInt,可以识别第一个小数点
- 隐式转换
- 算数运算符的隐式转换 X-0 X*1 X/1 X%1 true->1 false->0 undefined->NaN null->0 ''->0
- 比较运算符的隐式转换(===、!==无隐式转换)
- 转字符串
- String(需要转化的对象) 所有数据类型都可以转换,完全等效于隐式转换
- 需要转化的对象.toString() 注意:undefined或null不可用,因为两者都不能使用任何的.操作
- 隐式转换
- 加运算的两边存在字符串时字符串拼接的隐式转换 X+''
- 转布尔
- Boolean(需要转化的对象) 所有数据类型都可以转换,完全等效于隐式转换 注意:除了0、NaN、''、undefined、null、false转化为false;其他都会转化为布尔数据true
- 隐式转换
- 分支/循环的条件之中的隐式转换(只需要判断是否为0、NaN、''、undefined、null、false,否则为true)
- 逻辑运算符的隐式转换 !!X
所有的隐式转换都出现在运算符之中
js运算符
-
算数运算符:具有隐式的数值类型转换(当字符串为纯数字的情况下,转为数值类型,如果字符串包含了非数字字符,直接转为NaN) +正常为加法数学运算,当符号任意一边是字符串的时候,就会进行字符串的拼接 -*/%分别是减法、乘法、除法、取余的数学运算 取余运算的运用: 1.判断奇偶性:num%2,结果为0说明是偶数,结果为1说明奇数 2.获取一个数字的倒数n位
-
比较/关系运算符:在进行比较时具有隐式的数值类型转换(先转成数值类型,再进行比较;结果一定是布尔值)
- 常规比较: > 大于 < 小于 >= 大于等于 <= 小于等于
- 特殊比较: == 等于比较 只比较值是否相等,不考虑数据类型 === 全等于比较 值和数据类型都相同 != 不等于比较 !== 不全等于比较 注意:
- 如果参与比较的左右两边都是字符串,则是按位PK每个字符的十六进制的unicode号(十进制ascii码) 0-9< A-Z < a-z < 汉字 常识: 汉字的第一个字:一:unicode号:4e00 - ascii:19968;最后一个字:龥(yù):unicode号:9fa5 - ascii:40869; 0-9的ascii:48-57 A-Z的ascii:65-90 a-z的ascii:97-122 获取字符串中第一个字符的ascii码:str.charCodeAt(0)
- NaN参与任何比较运算结果都为false,所以没有办法使用普通的比较运算来判断x是不是NaN !isNaN(x);
- undefined == null;//true 区分:undefined === null; 全等:=== 要求数值相同,并且数据类型也要相同,不再带有隐式转换 !== 不再带有隐式转换的不全等比较
重写String方法,看出 == 和 === 的区别
function String(x){
if(x===undefined){
return "undefined";//return->返回,后面跟着的就是返回的结果
}else if(x===null){
return "null";
}else{
return x.toString();
}
}
想要判断多个条件,只能运用逻辑运算符
-
逻辑运算符:具有隐式的布尔类型转换(左右两边都转为布尔值,再参与判断;结果为布尔值)
- && 与运算 全部为true,结果为true;一个为false,结果为false
- || 或运算 全部为false,结果为false;一个为true,结果为true
- ! 非运算 颠倒布尔值(取反运算)
- 非布尔值的逻辑运算,会将数值转换为布尔值,然后再运算。但要注意返回的是原值。
- &&运算:如果第一个值为true,则返回第二个值。如果第一个值为false,直接返回第一个值
- ||运算(找true):如果第一个值为true,则返回第一个值;如果第一个值为false,则返回第二个值
- 注意:短路逻辑:如果前一个条件,已经可以得出最终结论了,没有必要看后续
- &&短路:如果前一个条件满足,才执行后一个操作,如果前一个条件不满足,则不管后续操作
目的:简化【简单的】分支:
- 一个条件一件事,满足就做,不满足就不做:if(){}
- 【简单的】- 操作只能有一句话:多句操作导致我们以后维护项目时观看/阅读代码不方便,往往以后很多操作可能就只有一句话 语法:条件&&(操作);
- ||短路:实现浏览器兼容性问题:二选一 如:e=e||window.event;
- &&短路:如果前一个条件满足,才执行后一个操作,如果前一个条件不满足,则不管后续操作
目的:简化【简单的】分支:
-
赋值运算符: = 进行赋值操作 += 加等于 例如n1+=3 相当于n1=n1+3 -= 减等于 *= 乘等于 /= 除等于 %= 取余等于
-
自增自减运算符: ++ 自增:在自身基础上+1 前置++:先改变值,再参与运算 后置++:先参与运算,再改变值 -- 自增:在自身基础上-1 前置-- 后置--
-
位运算: 左移:m << n,读作m左移了n位,翻译:m*2的n次方 右移:m >> n,读作m右移了n位,翻译:m/2的n次方 缺陷:虽然可以设置指数,但是底数只能固定为2 (更好用的:Math.pow(底数,指数))
-
三目运算:简化if...else... if...else if...else 语法:看条件满足否,满足则作操作1,不满足则作默认操作 1、条件?操作1:默认操作; 2、条件1?操作1:条件2?操作2:默认操作
特殊: 1、默认操作不能省略,省略后会报错 2、如果操作有多句话,还是推荐使用if分支,多句操作再同一行不方便以后维护
总结: if === &&短路 if...else === 三目运算 if...else if...else === 三目运算 操作多句话使用以上三个 操作一句话使用以上3个
舍入误差
浮点数计算时,由十进制转为二进制运算,其结果再由二进制转为十进制,这个过程中产生数据丢失,即为出现了舍入误差 解决办法1 采用.toFixed(n)方法,四舍五入,保留小数点后n为,消除舍入误差 (建议搭配parseFloat()使用) 解决办法2 将参与计算的小数同乘以相同的倍数,转为整数,再将结果除以该倍数,避免浮点数运算产生的数据丢失
条件分支语句
程序的流程控制语句:3种 1、顺序执行 - 默认,从上向下的依次执行 2、分支结构 - 通过条件的判断,选择部分代码执行 3、循环结构 - 通过条件的判断,选择要不要重复执行某些代码
-
if语句 if(){} 条件满足就执行if的{},不满足不执行 if(){}else{} 条件满足就执行if的{},不满足就执行else的{} if(){}else if(){} 哪一个条件满足就执行哪一个if的{},前面条件满足了,就不考虑后面的条件 if(){}else if(){}else{} 多个条件依次判断是否满足,满足则执行if的{},所有条件都不满足,执行else的{} 在()中书写条件 在{}中书写条件满足时执行的代码
-
switch语句 switch(表达式){ case n1:执行语句1
break;
case n2:执行语句2 break; case n3:执行语句3 break; ... default:默认执行语句 }
注:
- n1.n2...为表达式的值 case为全等于判断,不带有隐式转换,必须数值和数据类型相同才执行对应语句,不存在隐式转换
- break直接跳出当前语句,如果不写break,将向下穿透,无视case条件执行,直至break
- 建议:每一个case的操作后都跟上一个break;
有的地方也可以省略break:
- 最后的一个操作default可以省略break
- 如果中间多个条件,做的操作是一样的,也可以省略掉中间的操作
- default可以省略不写,如果条件都不满足的情况,则什么事都不会执行
==面试题:if和switch的比较?==
- switch:
- 好处:执行效率相对较高
- 缺点:必须要知道最后的结果才能使用,case不能做范围判断
- if:
- 好处:可以做范围判断
- 缺点:执行效率相对较低
- 开发时:用哪个都无所谓
- 代码优化:尽量的将if换成switch
可以利用向下穿透的特性来进行累计计算 例如:累计计算某一天为当年的第几天
<div>
<input type="date">
<p>请选择日期</p>
<button>点击计算</button>
</div>
<script>
var date = document.getElementsByTagName('input')[0]
var btn = document.getElementsByTagName("button")[0]
btn.onclick = function () {
// console.log(date.value)
var arr = date.value.split('-');
//拆解字符串 split
var year = Number(arr[0]);
var mouth = Number(arr[1]);
var day = Number(arr[2]);
var result = 0;
switch (mouth) {
case 12:
result += 30;
case 11:
result += 31;
case 10:
result += 30;
case 9:
result += 31;
case 8:
result += 31;
case 7:
result += 30;
case 6:
result += 31;
case 5:
result += 30;
case 4:
result += 31;
case 3:
if(year%4==0&&year%100!=0||year%400==0){
result+=29;
}
else{
result+=28;
}
case 2:
result += 31;
}
result+=day;
var p=document.getElementsByTagName('p')[0];
p.innerHTML="这是"+year+"年里的第"+result+"天";
}
</script>
循环结构语句
循环结构:反复执行【相同或相似】的操作时使用 循环三要素: 1.循环条件:开始 - 结束,循环的次数 2.循环体:做的操作是什么 3.循环变量:记录着我们当前在哪一次,而且他会不断的变化,往往都会向着不满足循环条件进行
- while语句 语法: var 循环变量=几; while(循环条件){ 循环体; 循环变量变化; } 执行原理:首先创建了循环变量,然后判断条件,如果条件满足,则做【一次】循环体操作,并不会退出循环,回过头继续判断条件是否满足,如果满足,则再做【一次】循环体操作.直到循环条件不满足,才会退出循环 宏观上感受循环一瞬间就结束了,但是微观上来说其实是【一次一次】执行的
- do while语句 do{}while(条件) 当初始变量在条件以外时,while语句不执行,do while语句执行一次
- for语句 语法: for(var 循环变量=几;循环条件;变量的变化){ 循环体; }
- 注意:
- 死循环:永远不会停下来的循环 何时使用:不确定循环次数的时候 写法:while(true){循环体;)或for( ; ; ){循环体;}
- 退出循环语句:
- break;//退出整个循环
- continue;//退出本次循环,还会继续接下来的循环
- 优先使用for循环,不确定循环次数的时候再用while补充
==面试题:while 和 for 的区别?== 语法上有区别,但两者都能做到相同的操作 一般来说我们不确定循环次数的时候,会使用while循环 - 死循环 一般来说我们确定循环次数的时候,就用for循环 - 更漂亮更简洁,大部分情况都会使用它 ==面试题:while和do...while的区别?== 除了写法上有区别,还有一个点:只看第一次 如果第一次大家都满足,两者其实没区别 如果第一次大家都不满足。while一次都不会执行,而do...while至少会执行一次
函数
自定义函数
也叫做方法,是需要预定义好的,以后可以反复使用的代码段
-
创建函数并调用
- 创建函数(2种方法)
- 声明方式创建函数:用关键字function做声明 function 函数名(形参列表){ 函数体; return 返回值; }
- 直接量方式创建函数: var 函数名=function(形参列表){ 函数体; return 返回值; } return的本意:退出函数的意思 只不过如果return后面跟着一个数据,会顺便将其返回到全局作用域中,但是只负责返回负责保存! 所以在调用函数时:如果有return,记得拿一个变量接住结果 何时使用:如果你希望拿到函数的结果,以后还要做别的操作,就需要搭配上return var result=函数名(实参列表);
- 调用/使用函数:
- 要么在js中程序员直接写死,要执行几次:函数名();
- 交给用户绑定在某个元素上,写上点击事件,让用户来触发
- 何时使用:
- 不希望打开页面立刻执行,而需要时再使用或由用户触发
- 希望能够反复执行,不用刷新页面
- 以后任何一个独立的功能体,都要单独封装为一个函数(你的每一个作业)
- 函数的地位非常高,函数是第一等公民地位,随时随地考虑能不能封装为一个函数,尤其是重复的代码
- 函数内的一切内存,函数调用完毕后都会自动释放
- 带参数的函数
- 定义:function 函数名(形参1,形参2,...){ 函数体; }
- 调用:函数名(实参1,实参2,...)
- 形参:形式参数,其实就是一个变量,但是不需要写var,而且默认也没有保存任何值,默认值为undefined
- 实参:实际参数,真正的值,需要再你调用时再传入
- 注意:
- 传实参的顺序一定要和形参的顺序一一对应,并且数量也要对应
- 不是一定要带参数的函数才是好函数,具体情况,需要具体分析:
- 如果函数体就是固定的,则使用普通函数
- 如果函数体希望根据传入的实参不同,做的略微不同,则使用带有参数的函数
- 创建函数(2种方法)
-
作用域
- 全局作用域:全局变量和全局函数,在任何地方都可以使用
- 函数/局部作用域:局部变量和局部函数,在【函数调用时内部可用】 =>变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
- 特殊:
- 千万不要对着未声明的变量直接赋值:a=1;//会导致全局污染,全局本来没有的东西,突然被添加一坨内存,建议创建变量时,记得一定要写var
- 儿子不孝啊:局部的东西全局居然不能用,解决:return↓
- 函数没写return或者写了return没有具体的值,默认return undefined
- return一般只会出现在函数的最后(之后的代码不执行),而且只能出现一个
- 往往前辈们提供的方法,底层都有一个return操作,前辈们觉得以后用这些方法的人,可能还需要拿着这个结果去做别的操作
-
声明提前:==笔试重点== 原理: 在程序正式执行之前, 会悄悄地将 var声明的变量 和 function声明的函数, 集中提前到当前作用域的顶部, 变量比函数轻, 但是赋值留在原地 明说: 自己写代码绝对不会碰到,只要我们遵守原则:1.先创建后使用 2.变量名和函数名尽量的不要重复; 只有笔试中碰到,如果你以后碰到先使用在创建,或者经常重复变量名,很有可能就是在考你声明提前; 先转为我们提前后的样子,再去判断;
-
按值传递 按值传递:两个变量之间进行赋值
- 如果传递的是原始类型的值: 修改一个变量,另一个变量是不会受到影响到,其实是复制了一个【副本】给对象
- 如果传递的是引用类型的对象: 修改一个变量,另一个变量其实也会受到影响,因为大家操作的其实是同一个【地址值】 - ==浅拷贝==
-
重载
略
- 匿名函数
略
- 闭包
略
预定义全局函数
前辈们提前写好的,我们程序员可以直接使用的,全局(在任何地方都可以使用)
- 编码和解码: 问题:url中不允许出现多字节字符,如果出现会乱码 utf-8编码格式下,一个汉字,占3字节 解决:发送前,前端将多字节字符编码为单字节字符(数字、字母) 发送后,后端接住,然后将单字节字符解码为原文 如: 编码:var code=encodeURIComponent("剑风传奇"); 解码:var 原文=decodeURIComponent(code); 其实这个东西在某次浏览器更新后,当前就淘汰了!浏览器现在自带此功能
- isFinite(num):判断num是不是无穷大,true->有效数字,false->无穷大 为false的情况:NaN、Infinity、分母为0,此方法不能用来判断是不是NaN
- 牛逼的:parseInt/Float()、isNaN()、eval()
.递归函数
function fn(){
if()return 1;
return fn(n-1)
}
一个函数调用自身,并设置了结束条件,即为正确的递归函数
.作用域
- 范围: 全局作用域:一个页面就是一个全局作用域 私有作用域:只有函数 生成私有作用域
- 使用: 定义:声明在什么位置的变量就是属于哪一个作用域的变量 访问:自己有用自己的,自己没有用父级的,全局没有即报错 赋值:自己有给自己赋值,自己没有给父级赋值,全局没有定义为全局变量
数组数据类型(array)
场景: 当需要保存多个数据时,不推荐使用变量,因为变量其实就是我们所谓的内存,变量创建的越多,那么我们内存空间消耗就越大,那么网站的性能就会越差.这种情况就使用数组.
定义:创建一个变量可以保存【多个数据】的集合 数组都是线性排列,除了第一个元素,每个元素都有唯一的前驱元素 除了最后一个元素,每个元素都有唯一的后继元素 每个元素都有一个自己的位置,称之为叫做下标(索引),下标是从0开始的,到最大长度-1 与对象不同点:不需要键名,自带顺序
创建一个数组 1.直接量方式: var arr=[];//空数组 var arr=[数据1,数据2,...]; 2.构造函数方式: var arr=new Array();//空数组 var arr=new Array(数据1,....);//==笔试考点==:此方法只写一个值的时候为数组长度,即一个定义了数组长度的空数组
数组具有三大不限制:
- 不限制元素的个数
- 不限制元素的类型
- 不限制元素的下标越界 - 不是一个好东西了 如果获取元素,下标越界,返回的一个undefined 如果添加元素,下标越界,会得到一个稀疏数组,导致下标不再连续,如果搭配上循环去遍历每一个元素的话,我们会得到很多很多的undefined
数组的操作
- 长度的操作
- 获取长度 arr.length 其值为最大下标+1
- 设置长度 arr.length=数值 长度小于原数组长度时,会按照顺序删除靠后的数据
- length的三个固定套路: 1. 获取倒数第n个元素:arr[arr.length-n] 2. 始终向末尾添加元素:arr[arr.length]=新值; 3. 缩容:删除倒数n个元素:arr.length-=n
- 数据的操作
- 获取数据 arr[索引值]
- 设置数据 arr[索引值]=数值 下标处没有元素为添加,有则替换
- 注意:下标越界
- 读取数据时,返回undefined
- 添加元素时,在新位置添加元素=>由于下标的不连续,而产生稀疏数组,稀疏数组遍历得到很多的undefined
数组的遍历 从头到尾依次访问数组的每一个数据即遍历 利用循环进行遍历,开始为0,结束为小于数组长度,步长为1,使用循环控制变量当做数组的索引来访问数组中的每一个数据
for(var i=0;i < arr.length;i++){
console.log(arr[i])
}
释放一个引用类型的对象:切记一定要看清楚这个对象有几个变量关联着,每个变量都要释放后才能真正的释放. 最好的方式就是封装为一个函数,因为函数中的东西,调用完毕都会自动释放
索引数组:下标都是数字组成的数组(默认) 关联(hash)数组:下标是可以自定义的数组 为什么要自定义下标:索引数组的下标无具体的意义,不便于我们查找
创建关联数组:
- 先创建一个空数组:var arr=[];
- 添加自定义下标并且赋值:arr["自定义下标"]=新值;
关联数组的操作:
- 访问:arr["自定义下标"];
- 遍历:
- 问题:不能使用for循环去遍历关联数组,因为关联数组的length永远为0,而且下标也不再是数字
- 解决办法:for in 循环(设置从哪里开始到哪里结束,所有的操作都是自动的,自动获取下标i)
- 语法:for(var i in 数组名){数组名[i];}
- 既可以遍历hash数组,也可以遍历索引数组
- 建议:索引数组依然使用for循环,关联数组再使用for in循环
==JS中除了undefined和null不是一个对象,万物皆对象,而【一切对象的底层都是hash数组】==
==面试题:hash数组的原理?== hash算法:将字符串交给hash算法,会得到一个尽量不重复的数字,但是字符串的内容相同,那么得到的数字也一定是相同 添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把要保存的数据放进去了 读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),通过这个地址值可以拿到当初保存的东西
数组常用方法API
共10个:join、concat、slice、splice、reverse、sort、push、pop、shift、unshift
不修改原数组的API:需要创建新变量接收 1.数组转为字符串 var str=arr.join("自定义连接符");//如果没有传入实参,则和toString效果一致,默认都是用,隔开
- ==面试题:完成无缝拼接== var arr=["h","e","l","l","o"," ","w","o","r","l","d"]; console.log(arr.join(""));
- 将数组元素拼接为页面元素(==数据渲染==) //获取数据 var arr=["-请选择-","北京","南京","西京","东京","重庆"]; //将数组转为了字符串,并且拼接上了标签 var str="<option>"+arr.join("</option><option>")+"</option>"; //让字符串上DOM树,innerHTML识别标签 sel.innerHTML=str;
- 实现二级联动关键点:
- 必须使用二维数组,细分每一个城市,并且二维数组的顺序要和之前的一维数组对应
- select.onchange=function(){} 状态改变事件:select的专属事件,只有选中项发生变化时,才会触发
- select可以直接获取当前选中项的下标,而不需要自定义下标:select.selectedIndex;
- 其实绑定事件,等号左边部分就是你的函数名
- 返回值:拼接后的字符串
2.拼接数组:添加元素到末尾的新方式 var newArr=arr.concat(值1,arr2....); 注意:
- 此方法如果拼接新数组,会打散数组,单个添加
- 返回值:拼接后的新数组
3.截取子数组:可能只想拿到数组中的某一部分 var subArr=arr.slice(starti,endi+1); 注意:
- 含头不含尾
- 只传入一个实参,则为从starti开始,到末尾
- 无实参,则复制了一份,即==深拷贝==(两者互不影响)
- 支持负数参数,-1代表倒数第一个,-n代表倒数第n个
- 返回值:以新数组的形式返回截取的数据
修改原数组的API: 4.删插替: splice:
- 删除:var dels=arr.splice(starti,n);//从starti位置开始删除n个元素
- 插入:var dels=arr.splice(starti,0,新值1,....);
注意:
- 原来starti位置的元素以及后续元素都会被向后移动
- 没有删除元素,也有返回值,返回的是一个空数组而已
- 替换:var dels=arr.splice(starti,n,新值1,....); 或 var dels=arr.splice(starti,0,新值1,....); 注意:删除的个数 和 插入的个数不必相同
- 返回值:以新数组的形式返回删除的数据
5.翻转数组:arr.reverse();//仅仅只能翻转数组顺序
6.数组排序
排序方法
冒泡排序(Bubble Sort) 思路: 1.遍历数组,比较相邻索引的数值大小,将索引靠前的大数值与后面的交换 2.重复多轮
// 定义一个乱序的数组
var arr=[2,1,6,9,4,5,3,8,7]
// 比较length-1轮
for(var j=1;j<arr.length;j++){
//一轮需要比较length-1-比较轮数 次
for(var i=0;i<arr.length-j;i++){
if(arr[i]>arr[i+1]){
//借助第三个变量,储存将要被重新赋值的数据
var temp=arr[i+1];
arr[i+1]=arr[i]
arr[i]=temp
}
}
}
console.log(arr)
选择排序(Select Sort) 思路: 1.先从0开始假定最小数值的索引 2.遍历数组与假定最小数值的比较,得出实际最小的数值的索引 3.将实际最小的数值的索引与假定最小数值的索引交换 4.重复多轮,每轮改变假定最小数值的索引
// 定义一个乱序的数组
var arr=[2,1,6,9,4,5,3,8,7];
// 进行数组长度-1轮的比较
for(var j=0;j<arr.length-1;j++){
// 假设最小数值的索引为j
var minindex=j;
// 循环遍历数组,从索引为1开始
for(var i=1+j;i<arr.length;i++){
// 判断是不是比假设索引位置的值小
if(arr[i]<arr[minindex]){
// 如果为true,替换最小数值的索引
minindex=i
}
}
// 交换假设的最小数值的索引和真实的最小数值的索引
var temp=arr[j];
arr[j]=arr[minindex];
arr[minindex]=temp;
}
console.log(arr)
语法:arr.sort();
- 默认转为字符串,按位PK每个字符的unicode(ascii)
- 按照数字排序=>引入匿名函数
- 升序:arr.sort(function(a,b){return a-b;}) a是后一个数,b是前一个数 如果a > b,就会返回一个正数,说明后一个数 > 前一个数 如果a < b,就会返回一个负数,说明后一个数 < 前一个数 如果a == b,就会返回一个0,说明后一个数==前一个数 而sort的底层就是通过返回的值来判断是否交换位置
- 降序:arr.sort(function(){return b-a;})
==以后网页中见到任何带有排序功能的特效,说明它的底层一定是数组,因为JS中只有数组可以排序,先排序再数据渲染==
7.栈和队列
- 栈:一端封闭,只能从另一端进出.使用场景:希望使用到最新的数据的时候
- 队列:只能一端进入,另一端出.使用场景:按照先来后到的顺序
- 作用:添加元素和删除元素的新方式
栈:
-
开头入:arr.unshift(新值,....)
-
开头出:var first=arr.shift();//一次只能删除一个,而且一定是删除的第一个元素 注意:开头进出,会导致每个元素的下标都会发生变化
-
结尾入:*arr.push(新值,...);
-
结尾出:var last=arr.pop();//一次只能删除一个,而且一定是删除的最后一个元素 注意:不会影响到其他人的位置
队列:以上4个API混搭
-
开头入:arr.unshift(新值,....)
-
结尾出:var last=arr.pop();
-
结尾入:*arr.push(新值,...);
-
开头出:var first=arr.shift();
pop和shift返回值为删除的数据,push和unshift返回值为最新的数组长度
二维数组
释义:数组的元素,又一次引用了一个数组 使用场景:在一个数组内再次细分分类
创建二维数组: var nums=[ [1,2,3], [4,5,6], [7,8,9] ];
访问二维数组的元素:arr[r][c] - r代表行下标,c代表列下标 注意:
- 列下标越界,返回undefined
- 行下标越界,返回报错,(行下标越界已经得到undefined再加[]则报错)
如何遍历: 固定公式:外层循环遍历行,内层循环遍历列 for(var r=0;r < nums.length;r++){ for(var c=0;c < nums[r].length;c++){ console.log(nums[r][c]) } }
字符串(String)
String的基础概念 什么是字符串:多个字符组成的【只读】字符【数组】
- 【只读】:字符串所有的API都不会修改原字符串,只会返回新的字符串。
- 【数组】:跟数组有相同点:
- 字符串可以使用下标获取某个字符
- 字符串可以使用length获取字符的长度
- 字符串可以遍历得到每个字符
- 字符串可以使用数组不修改原数组的API(concat、slice) 差异:所有数组直接修改原数组的API,字符串都不可以使用!字符串自己也有一堆API
JS内置对象(引用类型):11个
- String、Number、Boolean -> 包装类型
- Array、Function、Date(日期)、Math(数学)、RegExp(正则:验证)
- Error(错误)
- Object(面向对象)
- Global(全局对象)
- 保存着全局变量和全局函数,只不过浏览器端/客户端/前端global被window代替了,在Node.js后端语言中全局真的是global
- 唯独window对象可以省略不写
包装类型:专门封装原始类型的值,将原始类型悄悄的变成了引用类型的对象(从而具有了属性,并可使用方法) 本身原始类型的值,不带有任何属性和方法,意味着不能使用.去做操作的 何时使用:只要你试图使用.去操作原始类型的值的时候,包装类型就会悄悄出现 何时释放:方法一旦调用结束,包装类型就会自动释放 注意:undefined和null没有提供过包装类型,因此两者没有任何属性和方法,不饿能使用.操作
扩展: 周期性定时器:
- 开启:timer=setInterval(function(){操作;},间隔毫秒数)
- 停止:clearInterval(timer); 鼠标的移入和移出事件:
- onmouseover
- onmouseout