前端技术的发展速度你们有目共睹,js的ECMA标准也再也不是3的天下,但无论再怎么山雨欲来风满楼,基础语法仍是得温故而知新。不管你是初学则仍是多年js的编程者,均可以试着作作下面的测试题,我相信总仍是会有些收获的。由于所有是本身总结和手打的,有纰漏错误之处请留言,谢谢。javascript
一:考察基本数据类型与运算符前端
(1)未定义变量问题java
var a; console.log(typeof a); ==>undefined
先以一个最多见也是最简单的测试案例开始,未定义的变量或者未赋值则为undefined编程
(2)++/--运算符问题数组
var a = '1a'; console.log(a++); ==>NaN
++操做符将对a变量隐式转换为number类型,字符串'1a'没法正常转换为数字,因此返回NaN。函数
这里能够总结出如下几点:测试
1. 除了+操做符之外,-、*、/、%、++、--都将隐式转换参与运算的变量为number类型,若是能正常转换为数字则返回该数字,不然返回NaN;spa
2. 能正常转换为数字的有以下几种状况:prototype
纯数字类字符串如'123'、'1e2'(转换为1*10的2次方等于100);对象
null参与运算转换为0(null-4等于-4,null+null等于0);
boolean类型的true和false分别可转换为1和0;
3. 只有可以转换为数字的变量才能参与++或--运算,不然将报错,好比:
console.log(3++); ==>报错,常量不能直接运算++ var a = 3; console.log(a++); ==>3
其中有个特例:NaN++能够正常返回结果,仍然是NaN
(3)+运算符之四则运算与字符合并
console.log(2+'1'); ==>'21' console.log(2-'1'); ==>1 console.log(1+NaN); ==>NaN console.log('1'+NaN); ==>'1NaN'
1. +运算符有必要单独一提,由于除了+之外的其它算术运算符,都会对参与运算的变量或值默认隐式转换为number,但+由于在js中还肩负着字符串合并的重大任务,因此它有特殊'国情':
1.1 当+的左右两边均是数字类型时,则执行算术运算,好比1+2返回三、NaN+1返回NaN;
1.2 当+的左右两边均是字符串类型时,则执行字符串合并,好比'1'+'2'返回'12';
1.3 当+的左右两边一个是数字、一个是字符串类型时候,则先将数字转换为字符串再合并,好比1+'1'返回'11';
2. 在实际开发过程当中,咱们使用+运算符基本上都是处理字符串类型或者数字类型的,因此上面的三种状况可以应对大部分开发场景。可是当+运算符的左右两边出现了第三种数据类型时,状况就会显得复杂了(如下其它数据类型是指除了string和number的之外类型):
2.1 其它数据类型+字符串类型
console.log(null+'1'); ==>'null1' console.log(undefined+'1'); ==>'undefined1' console.log([1,2]+'1'); ==>'121' console.log((function(){})+'1'); ==>'function (){}1' console.log(({})+'1'); ==>'[object Object]1'
执行办法:其它数据类型将被转换为字符串再合并,且对象类型将调用自身toString()方法转换结果。另外,其实对象类型+运算不管另一个参与运算的值是否是字符串类型,都只能与它进行字符串合并操做,而不能是四则运算,下面会具体讲到。
2.3 其它数据类型+数字类型
console.log(null+1); ==>1 console.log(undefined+1); ==>NaN console.log(true+1); ==>2 console.log([1]+1); ==>'11' console.log((function(){})+1); ==>'function (){}1' console.log(({})+1); ==>'[object Object]1'
执行办法:非对象类型将进行四则运算,而对象类型场景则仍然是字符串合并的操做。
2.2 其它数据类型+其它数据类型
console.log(null+null); ==>0 console.log(undefined+undefined); ==>0 console.log(true+true); ==>2 console.log([1]+[2]); ==>'12' console.log((function(){})+(function(){})); ==>'function (){}function (){}' console.log(({})+({})); ==>'[object Object][object Object]'
执行办法:非对象类型将进行四则运算,而对象类型场景则仍然是字符串合并的操做。
因此,关于有其它类型参与+运算的场景,咱们能够再稍总结下最终的结果:只要有对象类型参与+运算,则永远是作字符串合并;若是是null/undefined/boolean类型参与+运算,当另外一个参与运算的值为字符串,则进行字符串合并,不然进行四则运算。
思考题:alert({name:'mofei'})
(4)+运算符之转换数字问题
console.log(1+ +1); ==>2 console.log(1e+1+1); ==>11
这个测试仍然是+运算,可是并无和上一个测试案例合并在一块儿而是单独出来,缘由很简单:此+非彼+。
+运算符实际上在js中有三种应用场景:转换为数字、四则运算加、字符串链接。在上一个测试案例中咱们讲了后两种应用场景,而这里是则是对第一个应用场景的补充。关于转换为数字的理解也不难,咱们常常用a+''的写法将一个变量转换为字符串类型,因此咱们也能够利用+运算符将其它类型转换为数值类型,好比+null返回结果为0。因此在这个案例中,1+ +1等同与1+1,由于后面那个+1其实就是将1转换为number类型,仍然是1,而1e+1+1等效于1e1+1,也就是11。
(5)除/取模运算符的极端场景问题
console.log(10/0); ==>Infinity console.log(10%0); ==>NaN
除0返回Infinity,对0取模(求除法运算的余数,对2取模经常使用在判断奇偶)返回NaN。
(6)!运算符问题
console.log(!!false); ==>false console.log(!!4); ==>true console.log(!!'false'); ==>true
这里考察了取反运算符。双取反实际上就是将运算对象强制转换为boolean型,其中最后一个要注意'false'自己是个非空字符串,转换为布尔值为true。
大部分状况下转布尔值都是返回true,除了如下几种状况:false自己、null、nudefined、空字符串''、数字0、数字NaN
思考题:!!undefined
(7)typeof运算符问题
console.log(typeof(0)); ==>number
console.log(typeof(NaN)); ==>number console.log(typeof('0')); ==>string console.log(typeof('false')); ==>string console.log(typeof(false)); ==>boolean console.log(typeof(undefined)); ==>undefined console.log(typeof(null)); ==>object console.log(typeof([1,2])); ==>object console.log(typeof(function(){})); ==>function
这里罗列了typeof能够返回的全部可能值:number、string、boolean、undefined、object、function
能够总结的知识点是:
1. 凡是带上引号的typeof就是string,而不须要管里面内容是什么,好比不要误觉得typeof('undefined')结果就是undefined
2. null、数组array、普通对象的typeof返回为object
3. 函数自己也是对象,可是它的typeof返回为特殊的function
4. 并不能依靠typeof所有分别出变量到底属于8种数据类型中的哪种(好比数组和普通对象),可是能够直接区分基本数据类型中的四种类型:number、string、boolean、undefined,若是要所有区分类型能够结合其它方法共同判断(如instanceof、constructor),或者使用Object.prototype.toString.call(...)
(8)宽松等于严格等问题
console.log(null == undefined); ==>true console.log(false == ''); ==>true console.log(false === !true); ==>true console.log([] === []); ==>false
关于等于运算符==:比较双方是否相等,这种比较是容许进行类型转换的,好比1 == '1'将返回true,至于它们是怎样进行类型转换能够参照《javascript权威指南》75页有很是详细的描述,这里再也不阐述了。严格等运算符常常在对象的比较中被考察,咱们要知道对象的比较是经过引用比较的,因此在这个测试案例中,它们虽然看上去很像,实际上是两个不一样的对象(这里也是数组),它们并无引用同一个地址,因此并不严格等,对象严格等的状况以下:
var a = []; var b = a; console.log(a === b); ==>true
b变量被赋值为a,a本质是对象,对象赋值为引用赋值,此时a和b公用一个地址,因此严格等成立。
此外,关于==还有个比较经典的问题:
console.log([] == ![]); ==>true
由于!运算符优先级缘由,将先执行![],因此这里等效于 [] == false,按照常识在boolean环境下空数组是转换为true的,可是实际上在==环境中,是经过转换为数字或字符串来比较的,当操做值有boolean类型时转换为数值比较,也就是[]转换为number类型为0,false转换为number类型为0,因此结果返回true。看上去这些繁琐的转换实在使人担心,但实际也没有这么糟糕,毕竟这种看上去“非人性”的结果在实际开发场景中极少遇到,当你有必定的经验的时候,绝大部分宽松相等的结果你仍是可以一眼识破的。
(9)或与问题
console.log(1&&2); ==>2 console.log(1||2); ==>1 console.log(1&&a=2); ==>error console.log(1&&(a=2)); ==>2
关于&&和||两个运算符,也是笔试中的常客。这里有几点须要注意:
1. &&和||返回的是表达式的值,而并非true或者false
2. 从左到右执行,&&左侧的表达式返回值若是转换布尔型为true时,则将执行右侧的表达式;||左侧的表达式返回值若是转换布尔型为true时,则直接返回该表达式返回值且再也不执行右侧表达式
有了以上两点,前两个测试则比较容易理解了,而对于1&&a=2,实际等同于——(1&&a)=2——undefined=2,执行将报错;只要给a=2加上小括号优先执行则能够正常运行,其中a=2的返回值为2,因此最终表达式的值为2。
(10)浮点数字不精确问题
console.log(0.1*0.1); ==>0.010000000000000002
在js中采用的是一种二进制表示法,能够精确的表示分数,好比1/2、1/8、1/1024。可是其它浮点值实际上只是真实值的一个近视表示,好比0.1,二进制浮点数表示法并不能精确的表示0.1这样简单的数字。因此,当遇到小数点的四则运算的时候须要特殊处理,最典型的场景就是支付了,好比1.1元每一个,用户购买3个,则不能直接使用相乘结果,可使用toFixed控制结果,或者以乘法为例可以使用如下方法保证精确性:
//乘法处理 function FloatMul(arg1,arg2) { var m=0,s1=arg1.toString(),s2=arg2.toString(); try{m+=s1.split(".")[1].length}catch(e){} try{m+=s2.split(".")[1].length}catch(e){} return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m); }