数据类型转换
强制转换
1、转字符串
1)var str = x.toString
x不能是undefined和null
2)var string = String(x)
2、转数字
1)、parseInt/Float(str)
2)、Number(x) 相当于隐式转换
3、转布尔
Boolean(x);任何数据都可以转为布尔
只有6个会转为false: 0/""/undefined/null/NaN/false
隐式转换
出现在运算符之中
运算符和表达式
1、算术运算符
符号: + - * / %
2、比较运算符:
符号:> < >= <= == != === !== 结果:布尔值 隐式转换,都转为一个数字,再比较
特殊
1)如果参与比较的左右两边都是字符串,则是按位PK每个字符的十六进制的unicode号(十进制ascii码) 0-9<A-Z<a-z<汉字:常识:汉字的第一个字:一: unicode号: 4e00 - ascii: 19968 ; 最后一个字:龥(yu) Unicode号,为9fa5 ascii为:40869;
2)NaN参与任何比较运算结果都为false,所以没有办法使用普通的比较运算来判断x是不是NaN !isNaN(x);
3)undefined==null
-------------- 区分:undefined===null
-------------- 全等:===要求数值相同,并且数据类型也要相同,不再带有隐式转换;
-------------- ===和!==不在具有隐式转换的不等式
3、逻辑运算符
符号: && || ! 作用:综合比较,结果也是布尔值 &&:全部满足才满足 ||:一个满足则满足 !:颠倒布尔值
短路逻辑
如果前一个条件,已经可以得出最终结论,没有必要看后续
1)、&&短路:如果前一个条件满足,才执行后一个条件;如果前一个条件不满足,则不管后续条件;
目的:简化简单的分支
----------1、一个条件一件事,满足就做,满足就不做 ==if(){}
----------2、简单的操作只能由有一句化
2)、||短路:实现浏览器兼容问题:二选一
--------e=e || window.event
4、位运算
1)、左移:m<<n,读作m左移了n位,翻译:m*2的n次方
2)、右移:m>>n,读作m右移了n位,翻译:m/2的n次方
----------底数只能固定为2,虽然可以设置幂,但是不能设置底数
5、赋值运算
符号:+= -= *= /= %= ++ -- 一句话完成两个操作,先计算,再赋值回去
++i和i++的区别?
1、单独使用时,放前放后无所谓,效果一样
2、但是如果参与了别的表达式,变量中的值都会+1
前++【返回的是加了过后】的新值;
后++【返回的是加了过前】的旧值
6、三目运算
简化:if..else if...else if...else
语法:看条件满足否,满足则作操作1,不满足则作默认操作
-----------1、条件?操作1:默认操作;
-----------2、条件1?操作1:条件2?操作2:默认操作
特殊:
1、默认操作不能省略,省略后会报错
2、如果操作有多句话,还是推荐使用if分支,多句操作再同一行不方便以后维护
保留小数
num.toFixed(d);//d代表保留的小数位数,会四舍五入运算
缺陷:返回的是要给字符串,建议搭配上一个parseFloat食用最好
自定义函数
创建函数并调用(2种)
1、声明方式创建函数
用一个关键字function做声明 function 函数名(形参列表){函数体;}
2、直接量方式创建函数
函数名其实是一个变量名
var 函数名 = function (形参列表){函数体}
调用函数:函数名(形参列表)
3、return 退出函数
- 只不过如果return后面跟着一个数据,会顺便将其返回到全局作用域中,但是只负责返回负责保存;
- 在调用函数时,如果有return,要用一个变量接住;
- 何时使用:如果若需要拿到函数的结果,以后还要做别的操作,就需要搭配上return。
作用域
1、全局作用域:全局变量和全局函数,再任何地方都可以使用 2、函数/局部作用域:局部变量和局部函数,在函数调用时内部使用
特殊
- 千万不要给未声明的变量直接赋值,会造成全局污染,所以在创建变量时一定要写var;
- 局部的全局不能用;
- 没有写return,其实最后也有return值,只不过是一个return undefined,不喜欢undefined,默认return undefined;
- return一般只会出现在函数的最后,而且只能出现一个
- 往往前辈们提供的方法,底层都有一个return操作,前辈们觉得以后用这些方法的人,可能还需要拿着这个结果去做别的操作
声明提前
- 原理:在程序正式执行之前,会将var声明的变量和function声明的函数,集中提前到当前作用域的顶部,变量比函数轻,但是赋值留在原地
- 遵守原则:1、先创建后使用 2、变量名和函数名尽量的不要重复只有笔试中碰到,如果以后碰到先使用在创建,或者经常重复变量名,很有可能就是在考你声明提前,先转为我们提前后的样子,再去判断
按值传递
- 若传递的是原始类型的值,修改一个变量,另一个变量是不会受到影响到,其实是复制了一个【副本】给对象;
- 若传递的是引用类型的值(例如Array和Function),修改一个变量,另一个变量其实也会受到影响,因为大家操作的其实是同一个【地址值】–浅拷贝
预定义全局函数
- 编码和解码(浏览器自带该功能,以后基本不用)
问题:url中不允许出啊先多字节的字符,如果出现会乱码,在utf-8中,一个汉字占3个字节
解决:
-----发送前,前端将多字节字符编码为单字节字符(数字、字母)
-----发送后,后端接住,然后将单字节字符解码为原文
语法:
-----编码:var code = encodeURI("文字");
-----解码: var 文字 = decodeURI("code");
-----升级版
---------编码:var code = encodeURIComponent(文字);
---------解码:var 文字 = decodeURIComponent(code); - isFinite(number) 判断number是否无穷大,true表明是有效数字,false表明是无穷大 为false的情况: NaN、Infinity、分母为0;
- 一般用是parseInt/Float,isNaN,eval;
分支结构
switch...case 根据条件不同,选择一部分代码执行 语法:
switch(变量/表达式){
case 值1: 操作1;
break;
case 值2: 操作2;
break;
case 值3: 操作3;
break;
default:操作;
break;
特殊
-
case的比较不带有隐式转换
-
问题:默认只要一个case满足,会将后面的操作都做完 ---解决:break; ---建议:每一个case的操作后面都跟上一个break,其中有的地方break也可以省略
1、最后的一个操作default可以省略break 2、如果中间多个条件,做的操作是一样的,也可以省略掉中间的操作 -
default也可以省略不写,如果条件不满足的情况,则什么是都不会执行
if和switch的比较
switch执行效率相对较高,但必须要知道最后结果才能使用,且不能做范围判断;if可以做范围判断,但执行效率相对较低;在开发时,都可以使用,但在代码优化时,尽量将if换成switch。
循环结构
-
while循环
-
do...while循环
var 循环变量 = 几;do{循环体;循环变量的变化;}while{循环条件;}while和do...while的区别 除了写法上有区别,只看第一次;如果第一次都满足,两者没有区别; 如果第—次大家都不满足。while—次都不会执行,而do..while至少会执行一次 -
for循环
-
终止循环语句
-------break 退出整个循环
-------continue 退出本次循环,还会继续做下一次循环
数组基础
一个变量可以存放多个数据
- 总的创建
- 直接量方式 var arr = [值1,值2,....]
- 构造函数方式 var arr = new Array(值1,值2...)
- 缺陷:new Array(3) 创建了一个长度为3的空数组
- 特殊:
- 读取元素,下标越界===返回undefined
- 添加元素,下标越界===在新位置添加元素,结果:不好的===稀疏数组,遍历时会得到很多undefined
-
索引数组 下标都是数字组成的数组--默认
-
hash数组 下标可以自定义的数组
- 如何创建
- 创建一个空数组 var arr = [];
- 添加自定义下标并赋值 : arr["自定义下标"]="新值"
- 访问:arr["自定义下标"];
- 遍历:把数组中的每一个元索取出来执行相同或相似的操作
- 问题:不能使用for循环去遍历关联数组,因为length失效了,关联数组的length永远为0,而且我们下标也不再是一个数字
- 解决:for in 循环
- 语法:for( var i in 数组名) {数组名[i]; // 当前hash数组中的元素了}
- 可以遍历hash数组,也可以遍历索引数组
- JS中,除了undefined和null不是一个对象,万物皆对象,而【—切对象的底层都是hash数组】
- hash数组的原理:【面试题】
- hash算法:将字符串交给hash算法,会得到一个尽量不重复的数字,但是字符串的内容相同,那么得到的数字也一定是相同;
- 添加元素:将自定义下标交给哈希算法,得到一个数字(地址值),把要保存的数据放进入了;
- 读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),通过这个地址值可以拿到当初保存的东西。
数组的API
-
数组转为字符串
---- 语法:arr.join("自定义符号");
----特殊
----------没有传入实参,则和toString效果一致,默认都是用,隔开
----------笔试中:完成无缝拼接
----------将数组元素拼接为页面元素(数据渲染)//获取数据 var arr=["-请选择-""北京""南京""西京""东京"∵"重庆""北京""南京,"西京""东京""重庆""北京","南京"]; //将数组转为了字符串,并且拼接上了标签 `var str=" <option>"+arr.join(" </option> <option>")+"</option>";` //让字符串上DOM树, innerHTMIL是识别标签 sel.innerHTML=str;
----------实现二级联动:3个关键点
---1、必须使用二维数组,细分每一个城市,并且二维数组的顺序要和之前的一维数组相对应
---2、select.onchange =function(){}--状态改变事件:只有选中项发生变化时,才会触发;
---3、select可以直接获取当前选中项的下标,而不需要自定义下标: select.selectedlndex;
---4、其实绑定事件,等号左边部分就是你的函数名;
2) 拼接数组:添加元素到末尾的新方式
var newArr = arr.concat(值1,值2....);
特殊:
----1、此方法不修改原数组,必须拿一个变量去接住结果(返回的是一个新数组)
----2、哪怕拼接的是一个数组,悄悄的打散数组,单个添加;
3) 截取子数组
var newArr=arr.slice(start,end+1);
特殊:
----1、此方法不修改原数组,必须拿一个变量去接住结果(返回的是一个新数组)
----2、含头不含尾
----3、如果只传入了一个实参,则为从start开始,到末尾
----4、如果两个实参都省略,则复制了一份–深拷贝!两者互不影响
----5、支持负数参数,-1代表倒数第一个,-n代表倒数第n个
-----------------------以上的API都不会修改原数组的-----------------------
4) 删插替
splice
- 删除:arr.splice(starti,n);//从starti位置开始删除n个元素
- 特殊:返回的是删除的元素组成的数组
- 插入:var dels = arr.splice(starti,0,新值1,....)
- 特殊
- 1、原来starti位置的元紊以及后续元紊都会被向后移动
- 2、没有删除元素,也有返回值,返回的是一个空数组而已
- 特殊
- 替换:var dels=arr.splice(starti,n,新值1..…); var dels=arr.splice(starti,0,新值1..…);
- 特殊:删除的个数和插入的个数不必相同
-
翻转数组:arr.reverse(); ---仅仅只能翻转
-
排序 手写冒泡排序,从第一个元素开始,依次比较两个相邻的元素,如果前一个>后一个,两者就要交换位置
var arr = [3, 255, 78, 111, 43, 65, 89]; 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; m = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = m; } } } console.log(arr);
语法:arr.sort();
问题:
------1、默认转为字符串,按位PK每一个字符的Unicode(ASCII)
------2、希望按照数字排序-升序
arr.sort(function(a,b){return a-b;}
a是后一个数,b是前一个数
//如果a>b,就会返回一个正数,说明后一个数>前一个数
//如果a<b,就会返回一个负数,说明后一个数<前一个数 、//如果a==b,就会返回—个0,说明后—个数==前—个数
//而sort的底层就能通过你返回的值来判断要不要帮你交换位苦
------3、希望按照数字排序-降序
---arr.sort(function(a,b){return b-a;}
切记:以后网页中见到任何带有排序功能的特效,说明它的底层一定是数组,因为JS中只有数组可以排序,先排序再数据渲染
队列和栈
栈:一端封闭,只能从一端进出
何时使用:希望使用到最新的数据的时候
开头入: arr.unshift(新值.....)
开头出:var first=arr.shift(); //一次只能删除一个,而且一定是删除的第一个元素,有可能删除的东西就是需要的东西,会影响其他元素
结尾入: arr.push(新值.....)
结尾出:var last=arr.pop();//一次只能删除一个,而且一定是删除的最后一个元素,不会影响其他元素
队列
只能一端进入,另一端出–现实生活中较多
何时使用:按照先来后到的顺序
开头入: arr.unshift(新值..)
结尾出: var last=arr.pop0;
结尾入: arr.push(新值..);
开头出: var first=arr.shift();
二维数组
数组的元素,又一次引用了一个数组
-
何时使用:希望在一个数组内再次细分分类
-
如何使用:
var peoples=[["梨花",18,"女"], ["张三",19,"男"], ["小红",20,"女"] ]; -
访问: arr[r][c] =====r代表行,c代表列
-
特殊:
------1、列下标越界,返回undefined
------2、行下标越界,会报错,因为行下标越界已经得到undefined再加上[]就会报错 -
遍历:
固定公式:外层循环遍历行,内层循环遍历列 for(var r=0;r<peoples.length;r++){ for(var c=0;c<peoples[r].length;c++){ console.log(peoples[r][c]) } }
总结:ES3提供的数组
- 数组的基础(创建、访问、添加、遍历、hash数组)
- 数组的API(10个: join、concat、slice、splice、reverse、sort、push、pop、shift、unshift)
- 二维数组
String的基础概念
字符串:多个字符组成的【只读】字符【数组】
- 只读: 字符所有的API都不会修改原文字字符串,只会返回新的字符串
- 跟数组有相同点: ------1、字符串可以使用下标获取某个字符 ------2、字符串可以使用length获取字符的长度 ------3、字符串可以遍历得到每个字符 ------4、字符串可以使用数组不修改原数组的API(concat \slice) ----差异:所有数组直接修改原数组的API,字符串都不可以使用!
JS内置对象(引用类型):11个
- String Number Boolean
----包装类型
--------------专门封装原始类型的值,降原类型悄悄的变成了引用类型的对象(属性和方法);前辈们觉得比如字将串经常会被我们拿来做一些操作,为了方便我们程序员,提供了包装类型,把字符串变成了一个对象,提供了我们一些操作字符串的同性和方法。
------何时使用:只要试图使用.操作原始类型的值时,包装类型就会悄悄出现
------何时释放:方法—旦调用结束,包装类型就会自动释放
------为什么undefined和null不能使用.,他们没有提供过包装类型(没有任何属性和方法) - Array Function Date(日期) Math(数学) RegExp(正则:验证)
- Error(错误)
- Object(面向对象)
- Global(全局对象) ----1、保存着全局变量和全局函数,只不过浏览器端/客户端/前端globa被window代替了 ----2、唯有window对象可以省略不写
周期性定时器
开启:
timer=setInterval(function(){操作;},间隔毫秒数)
停止:
clearInterval(timer);
鼠标的移入和移出事件
onmouseover
onmouseout