一.数据类型的转换
转字符串:
var str=x.toString() //x不能是undefined和null
var str=String(x) //万能,完全等效于隐式转换,不建议使用
页面上所有数据都是字符串
转数字:(重点)
var str=parseInt(x); //不支持转小数点
var str=parseFloat(x); //支持转小数点
原理:从左向右,依次读取每个字符,碰到非数字字符则停止,如果一来就不认识则为NaN
Number(x)//万能用法,等价于隐式转换,不如直接使用-0/1*1/%1 不建议使用
转布尔:
Boolean(x)//任何东西都可以转化为布尔值
0----null-----undefined------""--------NaN------false 只有这几个转布尔值是false,除了其他其他任何东西都是true
二.运算符
递增(++)递减(--)运算符
前置递增或者递减:先自加/减,后返回值
后置递增或者递减:先返回值,后自加/减
比较(关系)运算符
> 大于 < 小于 <= 大于等于 >= 小于等于 == 等于 === 全等于(值和数据类型完全一致) != 不等于 !== 不全等于
结果一定是布尔值,绝对不会手动使用,用来做判断,
隐式转换:默认,转为数字,判断大小
特殊:如果参与比较运算的左右两边都是字符串,则按位PK每个字符的16进制unicode号(ascii码值)
常用ASCII码值
0-9(ASCII码值:48-57) A-Z(ASCII码值:65-90) a-z(ASCII码值:97-122)
常识:汉字第一个字:一:unicode号4e00 -- 19968
最后一个字:龥 unicode号9fa5 -- 40869
str.charCodeAt(x);获取Ascii码 x是下标取值
NaN参与任何比较运算结果都为false,所以没有办法使用普通的比较运算来判断x是不是NaN
!isNaN(x);
undefined==null; 判断结果为true
undefined===null; 判断结果为false
重写String方法,看==与===的区别
function String(x){
if(x===undefined){
return"undefined";
}else if(x === null){
return"null";
}else{
return x.toString();
}
}
逻辑运算符
&& 逻辑与(and)两边条件都满足,返回true,否则返回false // 逻辑或(or) 两边任意一个条件满足,返回true,否则返回false ! 逻辑非(not)取相反值,如果是true则返回false
多个条件综合比较
特殊:短路逻辑 前一个满足条件,则执行下面的语句得出结论,没有必要看后续
&&短路:如果前一个条件满足,才执行后面一个条件,如果前一个条件不满足,则不管后续条件
可以用于简化简单的分支,一个条件一个事,满足就运行,不满足跳过==if(){}
||短路:实现浏览器兼容性问题
e=e||window.event;
赋值运算符
= 直接赋值 -- ++ 自加自减 ++i和i++在单独使用的时候没有区别 在参与表达式之后,变量中的值都会加一 前置递增或者递减:先自加/减,后返回值 ++i 后置递增或者递减:先返回值,后自加/减 i++ +=,-= 加,减后在赋值 *=,/=,%= 成,除,取模后在赋值
运算符优先级
小括号() 一元运算符 ++,--,! !非最先运算 算术运算符 先算*,/后算+,- 关系运算符 >,>=,<,<= 相等运算符 !=,=== 逻辑运算符 先看逻辑与在看逻辑或 赋值运算符 = 逗号运算符 ,
位运算
左移:m<<n m左移了n位 -- m*2的n次方 右移:m>>n m右移了n位 -- m/2的n次方 垃圾底数只能是2,虽然可以设置幂,但是不能设置底数
三目运算
语法:
条件?操作1:默认操作; 条件满足运行操作一,不满足就做默认操作
条件1?操作1:条件2?操作2:......:默认操作
特殊:
1.默认操作不能省略,省略后会报错
2.如果操作多句话,还是推荐使用if{}else{},一句话的时候推荐使用三目运算
三.自定义函数
自定义函数也叫方法,是需要预先定义好的,以后可以反复使用的代码段
***创建自定义函数
*声明方式创建函数:用一个关键字function()来声明
function 函数名(形参列表){
函数体;
return 返回值;
}
直接量方式创建函数
var 函数名=function(){ 函数体; return 返回值; } 函数名相当于变量名
return的本意是退出函数的意思, 只不过如果return后面跟着一个数据,会顺便将其放回到全局作用域中,但是只负责返回负责保存!所以在调用函数时:如果有return,记住拿一个变量接住返回值
何时使用:如果以后想要拿到函数的结果,执行别的操作时,就需要搭配上return
调用函数:函数名(实参列表);
作用域
1,全局作用域:全局变量和全局函数,在任何地方都可以使用
2,函数/局部作用域:局部变量和局部函数,在函数调用时内部可用
带来了变量的使用跪着:优先使用局部的,局部没有就找全局的,全局没有就报错
特殊:
1、千万不要对着未声明的变量直接赋值: a=1://会 导致全局污染,全局本来没有的东西,突然被添加一坨内存,建议创建变量时,记得一定要写var 2、儿子不孝啊:局部的东西全局居然不能用,解决:看上面 3、哪怕没有写return,其实最后也有return值, 只不过是一个return undefined,不喜欢undefined,默认return undefined 4、return- 般只会出现在函数的最后,而且只能出现-个 5、往往前辈们提供的方法,底层都有一个return操作, 前辈们觉得以后用这些方法的人,可能还需要拿着这个结果去做别的操作
笔试重点:***声明提前
原理:
在程序正式执行之前,会将var 声明的变量和function声明的函数,集中提前到当前作用域的顶部,变量比函数轻,但赋值留在原地
例如:
console.log(a); //按理说这里应该报错,但是结果为undefined
var a = 2;
console.log(a); //结果2
上面的实际表达是
var a;
console.log(a);
a=2;
console.log(a);
var f1; //f1 的值是undefined
f1(); //报错 undefined不能执行小括号操作
f1=function(){}
明说:自己写代码绝对不会碰到,只要我们遵守原则:
1、先创建后使用
2、变量名和函数名尽量的不要重复 只有笔试中碰到,如果你以后碰到先使用在创建,或者经常重复变量名,很有可能就是在考你声明提前,先转为我们提前后的样子,再去判断
***按值传递:两个变量之间进行赋值
如果传递的是原始类型的值
修改一个变量,另一个变量是不会受到影响的,其实是复制了一个副本给对象
如果传递的是引用类型的对象
其实目前已经学过两个了,Array和Function,JS中不是原始类型就是引用类型,修改一个变量, 另一个变量其实也会受影响,因为大家操作的其实是同一个地址值--浅拷贝
四.预定义全局函数
编码和解码:
问题:url不允许出现多字节字符,如果出现会乱码
utf-8编码格式下,一个汉字,占三个字节
解决:发送前,前端将多字节字符编码为单字节字符
发送后,后端接住,将单字节字符解码为原文
如何编码和解码
//编码
var code=encodeURLComponent("编码");
//解码
var code1=decodeURLComponent("code");
ifFinite(num):判断num是不是无穷大
如果显示true: 有效数字
如果显示false:无穷大 NaN,Infinity,分母为0的,所以有多个都为false,不能用来判断是不是NaN
五.***分支结构 switch case;
语法:
switch (变量或表达式){
case 值1:
操作1;break;
case 值2:
操作2;break;
case 值3:
操作3;break;
case 值4:
操作4;break;
.........
default:
默认操作;
}
特殊:case的比较不带隐式转换,需要自己转换数据类型在进行比较
认当case满足之后,会将后面没有执行的操作全部做完;所以在case操作后添加一个break。 default可以省略break;
如果中间多个操作是一样的,可以省略掉中间的操作;
default可以省略不写,如果条件都不满足,什么操作都不会执行
面试题:
if和switch的区别:
switch:
优点:执行效率高;缺点:必须要知道结果后才能使用,case不能判断范围
if:
优点:可以做范围判断; 缺点:执行效率相对来说较低
一般开发时两个都可以用;优化代码的时候尽量将if转为switch
六.***循环结构
while 和 do while
while
var 循环变量;
while(循环条件){
循环体;
循环变量的变化;
}
//while条件满足就执行里面的语句,不满足就不执行里面的语句
do while
var 循环变量;
do {
循环体;
循环变量的变化;
}while(循环条件)
//do while无论条件是否满足都会先运行一次,当陨心后不满足就直接结束循环
区别:
除了写法上有区别,只看第一次循环
如果第一次循环都满足,就没有区别
如果第一次循环都不满足,while一次也不会执行,而do while至少会执行一次循环
七.数组的基础
创建的两种方式:
直接量: var arr=[值1,值2,值3.....];
构造函数: var arr=new Array[值1,值2,值3.....];
面试题:构造函数在只给一个数字值时,他会默认识别成数组的长度,在给多个值的试试才会识别为数组里面的值。
例如:
var a = new Array(3); //该数组a的长度为3;
var b = new Array(3,4,5); //该数组的值分别是3,4,5
访问:数组名[下标] 可以得到某一个元素
例如:
var b = new Array(3,4,5); //该数组的值分别是3,4,5
alert(b[1]); //输出为4
特殊:读取元素,下标越界的时候返回undefined
添加元素,下标越界--在新位置添加元素:结果是不好的,下标不在连续---稀疏数组,拿去遍历的时候,会得到很大undefined
数组的三大不限制:
不限制数组长度
不限制数组类型
不限制数组下标越界 (这一点不限制是不好的)
数组长度 length的固定套路
给末尾添加元素: arr[arr.length]=新值;
获取倒数第N个元素: arr[arr.length-n];
缩容:删除倒数N个元素: arr.length-= n;
遍历数组
var a = [1,2,3,4,5,6,7,8,9,10];
for ( var i=0;i<a.length;i++){
console.log(a[i]);
}
释放一个引用类型的对象:
切记一定要看清楚这几个对象有几个变量关联着,每个变量都会释放后才能真正释放
最好的方式是封装一个函数,因为函数中的东西,调用完毕都会自动释放
新知识点:
索引数组:下标都是数字组成的数值--默认
关联(hash)数组:下标是可以自定义的数组
为什么要自定义下标;索引数组的下标无具体意义,不便于我们查找
关联(hash)数组:
创建: var arr=[ ];
添加自定义下标: arr["下标名"]=数组值;
访问: arr["自定义下标"]
问题:for循环不能遍历关联自定义数组了,length失效了(length永远是0,下标也不在是数字)
解决:for in 循环
for (var i in 数组名){ //i会自定获取每一个下标
console.log(数组名[i]); //当前的hash数组中的元素
}
可以遍历索引数组和关联数组
建议:索引数组使用for循环
关联数组使用for in 循环
例如:
var a=[],
a["姓名"]="盖伦",
a["攻击力"]=300,
a["生命值"]=2000,
a["防御力"]=200;
for(var i in a ){
console.log(a[i]);
}
JS中除了undefined和null以外,万物皆对象,一切对象的底层都是关联(hash)数组
面试题:
hash算法:会将字符串交给hash算法,会得到一个尽量不重复的数字,但是字符串内容相同的,得到的数字也会相同。
添加元素:会将自定义下标交给hash算法,得到一个数字(地址值),把要保存的数据放进去;
读取元素:会将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字,通过这个数字拿到当初保存的东西。
八.****数组API
数组转字符串***
arr.join("自定义连接符");
特殊:
1.如果没有传入太多的实参,则和toString效果一致,默认都用,隔开
2.面试笔试题:完成无缝拼接
固定套路:
var arr=["h","e","l","l","o","","w","o","r","l","d"]; console.log(arr.join(""));
3.将数组元素拼接为页面元素(数据渲染)
//获取数据 var arr=[*-请选择- ","北京","南京","西京","东京","重庆”,"北京",“南京","西京","东京","重庆","北京","南京","西京,"东京,"重庆","北京","南京","西京","东京","重庆“]; //将数组转为了字符串,并且拼接上了标签 var str="<option>"+ arr.join("</option> <option>")+"</option>"; //让字符串上DOM树,innerHTML是识别标签 sel.innerHTML =str;
实现二级联动:4个关键点
1.必须使用二维数组,细分每一个城市,并且二维数组的顺序要和之前的一维数组一一对应
2.select.οnchange=function(){}--状态改变时间:只有选中项发生变化时,才会触发
3.select可以直接获取当前选中项的下标,而不需要自定义下标“select.selectedindex;
4.其实绑定时间,=左边的部分就相当于函数名
拼接数组:添加元素到末尾的新方式
格式:
var newarr=arr.concat(值1,arr2..........);
特殊:
1.此方法不会修改原数组,必须拿一个变量去结束结果(返回的一个新数组)
2.哪怕拼接的是一个数组,悄悄的打散数组,单个添加
截取子数组:
arr.slice(start i.,end i+1) 开始截取下标,结束截取下标
var new=arr.slice
例如: var arr=[1,2,3,4,5]; var new=arr.slice(1,3); //2 3 var new=arr.slice(2); //3 4 5 var new=arr.slice(); // 1 2 3 4 5
1.此方法不会修改原数组,必须拿一个变量去结束结果
2.含头不含尾 开始下标是包含了的,结束的下标位置是不包含的
3.如果只传入一个实参,那么是从开始下标位置到数组最后一位
4.如果没有传入实参,那么数组全部内容都截取出来----深拷贝:两个数组互不影响
5.参数支持负数,-1代表倒数第一个,-n代表倒数第n个
上面的API不修改原数组的内容
下面的API会修改原数组的内容
1.删/插/替数组数据
删除:arr.splice();------arr.splice(下标开始,下标结束);
特殊:此方法返回你删除元素组成的数组----你删除的可以接着用一个变量接住拿着用
插入:arr.splice(开始位置下标,0,新值1,新值2........)
特殊:1.元素插入位置是从开始位置下标开始插入,会把原来的元素位置向后推
2.没有删除元素,也有返回值,返回的是一个空数组
替换:
arr.splice();------arr.splice(下标开始,下标结束);
arr.splice(开始位置下标,0,新值1,新值2........)
特殊:删除的个数和插入的个数可以不相同
翻转数组:arr.reverse()
★★★★★数组的API排序
冒泡法排序:
笔试面试:手写冒泡排序:从第一个元素和开始,依次比较两个
API排序:arr.sort();
默认转为字符串,按位PK每一个字符的ASCII码值进行排序
arr.sort(function(a,b)){}
升序:
arr.sort(function(a,b)){ return a-b; //a数组的后一个数,b数组的前一个数 } 匿名回调函数,不需要程序员调用,匿名回调函数,是前辈提供好的,我们只需要使用 如果a>b,就会返回一个正数,说明后面一个数>前面一个数 如果a<b,就会返回一个负数,说明后面一个数<前面一个数 如果a==b,就会返回0,说明后一个数==前一个数 而sort的底层就能通过你返回的值来判断要不要你交换位置
降序
arr.sort(function(a,b)){ return b-a; }
★★★以后网页中见到任何带有排序功功能的特效,说明它的底层一定是数组,因为JS中只有数组可以进行排列
栈和队列:添加元素和删除元素的新方式
栈:一端封闭,只能从另一端进出,现实生活中很少;希望使用到最新的数据的时候
队列:只能一端进入,另一端出;显示 生活中很多,按照先来后到的顺序
栈:
开头入:arr.unshift(新值,..);
开头出:var first=arr.shift();
一次只能删除一个,而且一定是删除的第一个元素,有可能删除的东西就是你需要的东西
★结尾入:arr.push(新值,...);
结尾出:var last=aar.pop();
一次只能删除一个,而且一定是删除的第一个元素,有可能删除的东西就是你需要的东西,不会影响到其他数组的位置
周期性定时器:
开启:setinterval(function(){}),毫秒数;
停止:clearinterval();
鼠标移出事件 onmouseover
鼠标移出事件 onmouseout
轮播图---低配版案例:
HTML代码:
<div id="ob" class="lunbo">
<img src="./img/banner.jpg" alt="">
<button><</button>
<button>></button>
</div>
css代码
*{
margin: 0;
padding: 0;
}
div{
width: 100%;
height: 500px;
position: relative;
}
div>img{
width: 100%;
height: 100%;
}
div>button{
width: 50px;
height: 50px;
position: absolute;
top: 50%;
margin-top: -25px;
}
div>button:nth-of-type(1){
left: 0;
}
div>button:nth-of-type(2){
right: 0;
}
JavaScript代码
var arr=["./img/banner01.jpg","./img/banner02.jpg","./img/banner03.jpg","./img/banner04.jpg"],//创建图片路径的数组
imgs=document.getElementsByTagName("img")[0],//拿到img标签
bnts=document.getElementsByTagName("button");//拿到所有的按钮
for(var i in bnts){ //遍历按钮数组,并且设置点击事件
bnts[i].onclick=function(){
if(this.innerText==">"){ //判断点击的是哪一个按钮:注意这里innerText是因为innerHTML会把输入的箭头识别为转义字符,所以使用innerText
var a=arr.shift();
arr.push(a);
imgs.src=arr[0];
}else{
var b=arr.pop();
arr.unshift(b);
imgs.src=arr[0];
}
}
}
shuffling = setInterval(function(){ //设置一个全局变量
var first=arr.shift();
arr.push(first);
imgs.src=arr[0];
},2000)
ob.onmouseover=function(){ //鼠标移入事件,ob是mouseout开启的局部的一个变量定时器
clearInterval(shuffling);
}
ob.onmouseout=function(){ // 鼠标移出的事件,如果加了var则为局部变量,不加var就是为了让ob这个变量,去到全局
shuffling = setInterval(function(){
var first=arr.shift();
arr.push(first);
img.src=arr[0];
},2000)
}
**二维数组
数组的元素,又一次引用一个数组
为何使用:你希望再一个数组再次细分类别
使用:
var peoples=[
[“盖伦","30","新疆"],
["卡特","29","重庆"],
["剑圣","31","重庆"],
]
console.log(peoples[1][0]);//卡特
console.log(peoples[1][2]);//重庆
访问二维数组:arr[r] [c] r代表行下标,c代表列下标
列下标越界,返回undefined
行下标越界,会报错
如何遍历二维数组
固定公式:外层循环遍历行,内层循环遍历列
for(var r=0;r<arr.length;i++){ for(var c=0;c<arr[i].length;c++){ console.log(arr[r][c]); } }
★★★★★String的基础概念
字符串:多个字符组成的只读字符数组
只读:
字符串所有API不会修改原来的字符串内容,只会返回新的字符串
数组:跟数组相同的点:
1.字符串可以使用下标获取某个字符
2.字符串可以使用length获得字符串长度
3.字符串可以遍历每一个字符
4.字符串可以使用数组不修改原数组的AIP(concat,slice)
JS内置对象(应用类型)11个
String,Number,Boolean
Array function Date(日期) Math(数学) RegExo(正则:验证)
Error(错误)
Object(面向对象)
Global(全局对象)
1、保存着全局变和全局函数,只不过浏览器端/客户端/前端global被window代替了
2、唯独window对象可以省略不写
包装类型:
专门封装原始类型的值,讲原始类型悄悄的变成了引用类型的对象(属性和方法)
使用包装类型:
只要试图去使用,去操作原始类型的值,包装类型就会悄悄出现
释放包装类型:
只要方法调用结束,包装类型就会自动释放