1.数据类型转换:
a.强制转换:
1.字符串转换:var str=x.toString; String(x);x不能是undefined和null,都不能用·操作。
2.转数字:
a.parseInt(x);
b.parseFloat(x);
c.Number(x);
3.转布尔
a.Boolean(x);
1.万能的任何人都可以转为布尔,绝对不会手动使用,不如!!x;
2.只有6个会转为false:0,“”,Undefined,Null,false,NaN;其余的都为true.
3.在分支循环的条件中自动隐私转换,都会悄悄变为一个布尔值,只需要判断是不是那6个会转为false。
b.隐式转换:都是出现在运算符之中。
复制代码
2.算术运算符和表达式:
a.算术运算符:+-*/%
特殊:
1.%取余,判断奇偶性。
2.具有隐私转换,默认转为数字在运算。
b.比较运算符:> < <= >= == != === !==
1.结果是一个布尔值。
2.隐式转换,默认转为数字在比较大小。
特殊:
1.如果参与比较的左右两边都是字符串,则是按位PK每个字符的十六进制Unicode号(ascii码)。
0-9<A-Z<a<z<汉字
汉字的第一个个字是“一”,Unicode号:4e00,ascii码:19968;最后一个字是龥,Unicode号是:9fa5,ascii码40869。
2.NaN参与任何比较运算结果都为false,所以没办法使用普通的比较运算符来判断x,是不是NaN.
3.undefined==null;--->true
区分:===全等,要求数值相同,并且数据的类型也要相同,不在带有隐式转换。
!==不带有隐式转换的不等比较。
c.逻辑运算符:综合比较,结果也是布尔值。
1.左右两边都会悄悄转为布尔值,在综合比较结果。
2.&&:全部满足才满足,一个不满足则不满足。
3.||:全部不满足才不满足,一个满足则满足。
4.!:颠倒布尔值。
5.**特殊:短路逻辑**
短路逻辑:如果前一个条件已经可以得出结论了,没必要看后续。
1.&&短路:如果前一个条件满足,则执行后续的操作,如果前一个条件不满足,则不看后续的操作。目的是为了简化简单的分支:if(){};简单的操作只能有一句话,多句话操作导致后期维护项目时观看不方便。
语法:条件&&(操作);
2.||短路:实现浏览器兼容问题:二选一执行。
语法:e=e||window.event;
d.位运算:
左移:m<<n,读作左移了n位,翻译:m*2的n次方。
右移:m>>n,读作右移了n位,翻译:m/2的n次方。
底数之恩固定为2,虽然剋设置幂,但是不能设置底数。
e.赋值运算:+= -= *= /= %= ++ --
一句话完成两个操作,先计算再赋值回去。
i++:递增,每次固定+1.
i+=1:累加,每次加几次由自己决定。
i=i+1
算法题i++和++i的区别?
1.单独使用时++放前放后的效果一致。
2.但是参与了别的表达式,变量中的值都会+1.
++i返回的是加了之后的值;----新值
i++返回的是加之前的值;----旧值
f.三目运算:简化if...else... if...elseif...else...
语法:条件1?操作1:条件2?操作2:默认操作;
特殊:默认操作不能省略,不然会报错,如果操作有朵菊花,还是使用if分支结构。操作再同一行不方便后期维护。
g.总结:
if-------&&短路;
if...else-----三目运算;
if...else if...else----三目运算;
操作多句话使用if分支结构
h.保留小数位数:计算机带有摄入误差。
解决:num.toFixed(d);
d代表小数的位数,会进行四舍五入。
获取字符串第一个字ascii码:Str.charCodeAt(0);
复制代码
3.自定义函数
概念:自定义函数也叫方法,是需要自定义好的以后可以反复使用的代码段。
a.创建函数并调用的方式:2种
1.声明方式创建函数:用一个关键字function做声明
function 函数名(形参列表){
函数体;
return返回值;
}
调用:var result=函数名(实参列表);
2.直接量方式创建函数:函数名其实就是一个变量名。
var 函数名=function(形参列表){
函数体;
return返回值;
}
调用:var result=函数名(实参列表);
return的本意是退出函数的意思。
只不过return的后面跟着一个数据,会顺便将其返回到全局作用域中,但是只负责返回不保存;所以再调用函数时,return的返回值需要用一个变量接收结果。
何时使用?如果希望拿到函数的结果,以后还需要做别的操作就需要搭配上return。
调用函数:var result=函数名(实参列表);
b.作用域:2种
1.全局作用域:全局变量和全局函数再任何地方都可以使用。
2.函数、局部作用域:局部的变量和局部函数在“调用时”内部可以使用。
变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错。
特殊:
1.千万不要对着未声明的变量直接赋值,a=1,全局本来没有的东西突然增加会导致全局污染,创建变量时尽量写上var;
2.局部的东西全局不能直接使用,需要return返回值并保存在一个变量中。
3.哪怕没有写return,其实最后也会有一个return,只是返回的值时undefined。
4.return一般只会出现在函数最后,而且只有1个。
5.提供的方法底层都有一个return操作,后期还会使用这个值做其他的操作。
c.声明提前:
原理:在程序正式执行前,会悄悄地将var声明的变量和function声明的函数集中提前到当前作用域的顶部,变量比函数轻提前在前面,但是赋值留在原地。
d.按值传递:两个变量之间进行赋值。
1.如果传递的是原始类型的值:
修改一个变量另一个变量不会受到影响,其实是复制了一个副本。
2.如果传递的是引用类型对象:
Array和function,js之中不是原始值类型就是引用类型,修改一个变量,另一个变量其实也会受到影响,因为大家操作的是同一个地址值,浅拷贝。
复制代码
4.预定义全局函数
a.编码和解码:是浏览器自带功能。
1.url中不允许出现多字节字符,如果出现就会乱码;utf-8格式下一个汉字3个字符。
2.编码:var code=encode URIComponent("");
3.解码:var 原文=decode URIComponent(code);
b.isFinite(num):判断num是不是无穷大,true--有效数字,false--无穷大。
false:NaN/Infinity/分母为0/有多个为false,所以不能判断是否为NaN。
c.分支结构:switch...case...根据条件不同选择一部分代码执行。
语法:
switch(变量/表达式){
case 值1:
操作1;
break;
case 值2:
操作2;
break;
default:
默认操作;
}
特殊:
1.case的比较运算不带有隐式转换。
2.默认只要一个case满足后,会将后面的操作全部做完,所以每一个case后面尽量都写break。
3.最后一个操作的default可以省略break。
4.如果中间有多个条件,做的操作是一样的也可以省略中间操作。
5.default可以省略不写,如果条件都不满足的情况下则什么都不执行。
if和switch...case的区别?
1.if
优点:可以做范围判断;
缺点:执行效率相对较低。
2.switch...case
优点:执行效率高;
缺点:必须知道最后结果才能使用,case不能做范围判断,且不带隐式转换。
复制代码
5.循环结构
a.var 循环变量=几;
while(循环条件){
循环体;
循环变量的变化;
}
b.var 循环变量=几;
do{
循环体;
循环变量的变化;
}while(循环条件)
c.***for(var 循环变量=几;循环条件;循环变量的变化){
循环体;
}
建议:优先使用for循环,不确定循环次数的时候再用while补充
d.终止循环语句:
break;//退出整个循环
continue;//退出本次循环,还会继续做下一次
e.****while和do...while的区别?
除了写法上有区别,还有一个点:
只看第一次如果第一次大家都满足,两者其实没区别
如果第一次大家都不满足。while一次都不会执行,而do...while至少会执行一次
复制代码
6.数组基础
概念:一个变量名可以保存多个数据
A.索引数组:下标都是由数字组成的数组,数字无意义不便于查找
a.创建数组的方式:2种
1.直接量方式:var arr=[值1,...];
2.构造函数方式:var arr=new Array(值1,...);
缺陷:new Array(3);是创建了一个长度为3的空数组。
b.访问
数组名[下标]---拿到某一个元素
特殊:读取元素下标越界返回undefined;添加元素下标越界,在新的位置添加元素,如果下标不连续则会得到一个稀疏数组,遍历会得到很多undefined。
c.length的三个固定套路
1.向末尾添加元素:arr[arr.length]=新值;
2.获取倒数第n个数:arr[arr.length-n];
3.缩容,删除倒数n个数:arr.length-=n;
B.关联数组/hash数组:下边是自定义的数组,下标具有意义方便查找。
a.创建hash数组
1.创建数组:var arr=[];
2.添加自定义下标并赋值:arr["自定义下标"]=新值;
b.访问
arr["自定义下标"];
c.遍历:自定义下标长度失效不能使用for循环遍历,使用for in遍历。
语法:for(var i in 数组名){
i;自动得到每一个下标;
数组名[i];但钱hash数组中的元素;
}
for in即可以遍历索引数组也可以遍历hash数组。
js之中除了undefined和null不是对象,万物皆对象,而一切对对象的底层都是hash数组。
d.hash数组原理
1.hash算法,将字符串交给hash算法,会得到一个尽量不重复的数字,但字符串内容相同,得到的数字相同。
2.添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把要保存的数据放进去。
3.读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字,通过这个地址值可以拿到当初保存的东西。
C.*****数组的API:
其实就是前辈提前定义好的一些函数,我们可以直接使用,这些函数的只有数组才可以使用。
1.不会修改元素的方法
a.数组转为字符串
1.语法:var str=arr.join("自定义连接符");
2.特殊:
1.如果没有传入实参,则toString的效果时一致的,默认都用逗号,隔开。
2.固定套路:
a.无缝拼接
var arr=["h","e","l","l","o"];
console.log(arr.join(""));
b.将数组元素拼接为页面元素
var arr=["北京","重庆","江西","四川","天津"];
var str="<option>"+arr.join("</option><option>")+"</option>";
select.innerHTML=str;
c.实现二级联动的4个关键点
1.必须使用二位数组,并且二位数组的顺序和之前的一维要对应上。
2.select.onchange=function(){}--状态改变事件,只有选中选时发生该改变才能触发。
3.select可以直接获取当前选中项的下标,而不需要定义下标。selectedIndex;专属。
4.绑定事件等号左部分就是函数名。
b.拼接数组:添加元素到末尾的新方式
1.语法:
var newArr=arr.concat(值1,arr2,.....);
2.特殊:
a.此方法不会修改原数组,必须拿一个变量去接收结果,返回的是一个新的数组。
b.如果拼接的是一个数组,也会悄悄的打散数组单个添加。
c.截取子数组:可能只想拿到数组中的某一部分元素。
1.语法:var subArr=arr.slice(starti,endi+1);
2.特殊:
a.此方法不会修改原数组,必须拿一个变量来接收,返回的是一个新的数组。
b.含头不含尾。
c.如果之传入了一个实参,则为从stari开始到末尾。
d.如果两个实参都神略,则相当于赋值了一份,也叫神拷贝,两者之间互不影响。
e.支持负数,-1代表倒数第一个,-n代表倒第n个。
2.修改原数组的API
d.删插替:splice
1.删除:var dels=arr.splice(strai,n);从开始下标处开始删除n个元素。
特殊:返回的是删除元素组成的新数组,有可能删除的部分是后续需要的元素。
2.插入:var dels=arr.splice(strai,0,新值1...);
特殊:
a.原来starti位置的元素以及后续元素都会被向后移动。
b.没有删除元素也有返回的值,返回的是一个空数组。
3.替换:var dels=arr.splice(strai,n,新值1...);
var dels=arr.splice(strai,0,新值1...);
特殊:删除的个数和插入的个数不必相同。
e.翻转数据:arr.reverse();只能反转数据。
f.排序
1.手写冒泡排序:
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;
}
}
}
语法:arr.sort();
特殊:
a.默认转为字符串,按位pk每个字符的Unicode码(ascii码);
b.希望按照数字排序---升序
arr.sort(function(a,b){
return a-b;
})
a是后一个数字,b是前一个数字,
如果a>b就会返回一个正数,说明后一个数>前一个数。
如果a<b就返回一个负数,说明后一个数<前一个数。
如果a=b就返回一个0,说明前后两个数相等。
sort的底层能通过返回的值来判断是否需要交换位置。
c.按照降序排列
arr.sort(function(a,b){
return b-a;
}
网页中任何带有排序功能的特效,说明它的底层都是数组,因为JS只有数组可以排序,先排序再数据渲染。
2.栈和队列:
a.作用:添加元素和删除元素的新方式。
b.栈:一端封闭,只能从另一端进出,只有希望使用到最新数据时才会用到。
c.队列:只能一端进入,另一个端出,只有按照先后顺序的时候才会使用。
1.栈:
a.开头入、开头出会导致每个元素的下标都发生变化。
开头入:arr.unshift(新值,...);
开头出:var first=arr.shift();一次只能删一个,删掉的内容可能时会用到的,需要用变量保存。
b.结尾入、结尾出,不会影响到别人的位置。
结尾入:arr.push(新值,...);
结尾出:var last=arr.pop();一次只能删一个,删掉的内容可能时会用到的,需要用变量保存。
2.队列:
a.开头入、结尾出
开头入:arr.unshift(新值,...);
结尾出:var last=arr.pop();
b.结尾入、开头出
结尾入:arr.push(新值,...);
开头出:var first=arr.shift();
D.二维数组:数组的元素,又一次引用了一个数组
1.何时使用:你希望再一个数组内再次细分分类
2.如何使用:
var city=[
["江北","沙坪坝","九龙坡"],
["成都","遂宁","广安"],
];
3.访问:arr[r][c] - r代表行下标,c代表列下标
4.特殊:
a.列下标越界,返回undefined
b.行下标越界,返回报错,因为行下标越界已经得到undefined再加[]则报错
5.如何遍历:
固定公式:外层循环遍历行,内层循环遍历列
for(var r=0;r<city.length;r++){
for(var c=0;c<city[r].length;c++){
console.log(peoples[r][c])
}
}
复制代码
总结:ES3提供的数组:
1、数组的基础(创建、访问、添加、遍历、hash数组)
2、数组的API(10个:join、concat、slice、splice、reverse、sort、push、pop、shift、unshift)
3、二维数组
复制代码
7.String的基础概念
a.什么是字符串:多个字符组成的【只读】字符【数组】!
1、【只读】:字符串所有的API都不会修改原字符串,只会返回新的字符串。
2、【数组】:跟数组有相同点:
1、字符串可以使用下标获取某个字符
2、字符串可以使用length获取字符的长度
3、字符串可以遍历得到每个字符
4、字符串可以使用数组不修改原数组的API(concat、slice)
b.JS内置对象(引用类型):11个
String Number Boolean -> 包装类型
Array Function Date(日期) Math(数学) RegExp(正则:验证)
Error(错误)
Object(面向对象)
Global(全局对象):
a.全局对象:
1、保存着全局变量和全局函数,只不过浏览器端/客户端/前端global被window代替了,以后我们学习Node.js后端语言的时候你会发全局真的是global
2、唯独window对象可以省略不写
b.包装类型:
1.专门封装原始类型的值,将原始类型悄悄的变成了引用类型的对象(属性和方法)
2.为什么:前辈们觉得比如字符串经常会被我们拿来做一些操作,为了方便我们程序员,提供了包装类型,把字符串变成了一个对象,提供了我们一些操作字符串的属性和方法
3.本身原始类型的值,不带有任何属性和方法,意味着不能使用.去做操作的
4.何时使用:只要你试图使用.去操作原始类型的值的时候,包装类型就会悄悄出现
5.何时释放:方法一旦调用结束,包装类型就会自动释放
为什么undefined和null不能使用.,他们俩没有提供过包装类型(没有任何属性和方法)
作者:用户41669486605
链接:https://juejin.cn/post/7136553418952278053
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。