前言总括: 这是笔者平时积累的一些觉得比较有意思或是比较有难度的javascript题目理解和心得,会保持长期更新。
人生莫作妇人身,百年苦乐由他人。
正文1.settimeout和setinterval深入理解在settimeout和setinterval深入理解这篇博客里笔者曾做过总结,我们知道javascript试单线程的产物,两个函数就是利用了插入代码的方式实现了伪异步,和ajax的原理实际上是一样的。下面来看下这个例子:
console.log(1);settimeout(function(){ console.log(3)},0); console.log(2);
结果:控制台依次输出1,2,3;
function fn() { settimeout(function(){alert('can you see me?');},1000); while(true) {}}
你觉得这段代码的执行结果是什么呢?答案是,alert永远不会出现。
这是为什么呢?因为,while这段代码没有执行完,所以插入在后面的代码便永远不会执行。
综上所述,其实js终归是单线程产物。无论如何“异步”都不可能突破单线程这个障碍。所以许多的“异步调用”(包括ajax)事实上也只是“伪异步”而已。只要理解了这么一个概念,也许理解settimeout和setinterval也就不难了。
2. 闭包初探小题在javascript闭包初探这篇博客里面进行了初步探讨,有几个小题个人觉得还是比较有意思的:
var name = the window;var object = {name : my object,getnamefunc : function(){return function(){return this.name;};}};alert(object.getnamefunc()());//the window
var name = the window;var object = {name : my object,getnamefunc : function(){var that = this;return function(){return that.name;};}};alert(object.getnamefunc()());//my object
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } };}var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,?var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,?
//问:三行a,b,c的输出分别是什么?
这是一道非常典型的js闭包问题。其中嵌套了三层fun函数,搞清楚每层fun的函数是那个fun函数尤为重要。
//答案:
//a: undefined,0,0,0
//b: undefined,0,1,2
//c: undefined,0,1,1
3. array/map,number/parseint[1, 2, 3].map(parseint)//求输出结果复制代码
首先, map接受两个参数, 一个回调函数 callback, 一个回调函数的this值
其中回调函数接受三个参数 currentvalue, index, arrary;而题目中, map只传入了回调函数--parseint.其次, parseint 只接受两个两个参数 string, radix(基数). radix的合法区间是2-36. 0或是默认是10.所以本题即问
parseint('1', 0);parseint('2', 1);parseint('3', 2);复制代码
后两者参数不合法.所以答案是:[1, nan, nan];
4. 0.1+0.2!=0.3和9999999999999999 == 10000000000000000;根据语言规范,javascript 采用“ieee 754 标准定义的双精度64位格式”(double-precision 64-bit format ieee 754 values)表示数字。据此我们能得到一个有趣的结论,和其他编程语言(如 c 和 java)不同,javascript 不区分整数值和浮点数值,所有数字在 javascript 中均用浮点数值表示,所以在进行数字运算的时候要特别注意。精度丢失看看下面的例子:
0.1 + 0.2 = 0.30000000000000004复制代码
在具体实现时,整数值通常被视为32位整型变量,在个别实现(如某些浏览器)中也以32位整型变量的形式进行存储,直到它被用于执行某些32位整型不支持的操作,这是为了便于进行位操作。大整数精度在2的53次方以内是不会丢失的,也就是说浏览器能精确计算math.pow(2,53)以内所有的数,小数精度,当十进制小数的二进制表示的有限数字不超过 52 位时,在 javascript 里也是可以精确存储的。
解决办法:math.round( (.1+.2)*100)/100;
5. [1fe18ec71a3529e35bd2449ea120bcf1a1&&27ba14dda2b473dcafde97e909b130e88true;truee5dfd1e04a098d470fd53bdae68047611e5dfd1e04a098d470fd53bdae6804761true;325346d3d65c60a4c2739f19f2f21fdd8true;false66a8cecc548e92eefe204758893a9e9e066a8cecc548e92eefe204758893a9e9etrue;复制代码答案:[true,true] 这个题的重点是对于运算符的理解,一是javascript对于不同类型数值的比较规则,详见js比较表,javascript相等性判断;二是对于比较操作符和赋值运算符的理解,即一个自左向右一个自右向左~
6. 浏览器懵逼史(1)3.tostring;3..tostring;3...tostring;复制代码
这个题感觉脑洞很大啊~先说答案:error,'3',error;
可如果是
var a=3;a.tostring;复制代码
却又合法了答案就是'3';
为啥呢?
因为在js中1.1,1.,.1都是合法数字啊!那么在解析3.tostring的时候到底是这是个数字呢,还是方法调用呢?浏览器就懵逼了呗,只能抛出一个error,所以说感觉此题就是在戏耍浏览器......
7. 声明提升var name = 'world!';(function () { if (typeof name === 'undefined') { var name = 'jack'; console.log('goodbye ' + name); } else { console.log('hello ' + name); }})();
答案是什么呢...笔者第一次做的时候傻傻的觉得是hello,world...实则不然,正确答案是:goodbye jack;
为什么呢,声明提升...上述代码相当于下面的代码:
var name = 'world!';(function () { var name; if (typeof name === 'undefined') { name = 'jack'; console.log('goodbye ' + name); } else { console.log('hello ' + name); }})();
8. 坑爹史(1)var a = [0];if ([0]) { console.log(a == true);} else { console.log(wut);}
读者们你们觉得此题答案是什么呢?true?因为[0]被看做boolean是被认为是true,理所当然的推出来[0]==true,控制台输出true...看似没错,然而并不是这样滴~[0]这个玩意儿在单独使用的时候是被认为是true的,但用作比较的时候它是false...所以正确答案是false;不信的话,f12控制台输出[0]==false;看是不是true......
###9. 坑爹史(2)
1 + - + + + - + 1
这题应该是等同于:(倒着看)
1 + (a) => 2a = - (b) => 1b = + (c) => -1c = + (d) => -1d = + (e) => -1e = + (f) => -1f = - (g) => -1g = + 1 => 1
答案是2
10. 坑爹史(3)function sideffecting(ary) { ary[0] = ary[2];}function bar(a,b,c) { c = 10 sideffecting(arguments); return a + b + c;}bar(1,1,1)
此题涉及es6语法,实在坑的不行...arguments
首先 the arguments object is an array-like object corresponding to the arguments passed to a function.也就是说 arguments 是一个 object, c 就是 arguments2, 所以对于 c 的修改就是对 arguments2 的修改.
所以答案是 21.
然而!!!!!!
当函数参数涉及到 any rest parameters, any default parameters or any destructured parameters 的时候, 这个 arguments 就不在是一个 mapped arguments object 了.....请看:
function sideffecting(ary) { ary[0] = ary[2];}function bar(a,b,c=3) { c = 10 sideffecting(arguments); return a + b + c;}bar(1,1,1)
答案是12...
请读者细细体会!!
11. 坑爹史(4)[,,,].join(, )
[,,,] => [undefined × 3]
因为javascript 在定义数组的时候允许最后一个元素后跟一个,, 所以这是个长度为三的稀疏数组(这是长度为三, 并没有 0, 1, 2三个属性哦)
答案: , ,
12. 浏览器懵逼史(2)var a = {class: animal, name: 'fido'};a.class
这个题比较流氓.. 因为是浏览器相关, class是个保留字(现在是个关键字了);fuck!
所以答案不重要, 重要的是自己在取属性名称的时候尽量避免保留字. 如果使用的话请加引号 a['class']
13.一道容易被人轻视的面试题function foo() { getname = function () { alert (1); }; return this;}foo.getname = function () { alert (2);};foo.prototype.getname = function () { alert (3);};var getname = function () { alert (4);};function getname() { alert (5);}//请写出以下输出结果:foo.getname();getname();foo().getname();getname();new foo.getname();new foo().getname();new new foo().getname();
14.闭包小题for(var i = 0; i < 5; i++) { console.log(i);}for(var i = 0; i < 5; i++) { settimeout(function() { console.log(i); }, 1000 * i);}for(var i = 0; i < 5; i++) { (function(i) { settimeout(function() { console.log(i); }, i * 1000); })(i);}for(var i = 0; i < 5; i++) { (function() { settimeout(function() { console.log(i); }, i * 1000); })(i);}for(var i = 0; i < 5; i++) { settimeout((function(i) { console.log(i); })(i), i * 1000);}settimeout(function() { console.log(1)}, 0);new promise(function executor(resolve) { console.log(2); for( var i=0 ; i<10000 ; i++ ) { i == 9999 && resolve(); } console.log(3);}).then(function() { console.log(4);});console.log(5);
15. 函数的隐式转换function fn() { return 20;}console.log(fn + 10); // 输出结果是多少function fn() { return 20;}fn.tostring = function() { return 10;}console.log(fn + 10); // 输出结果是多少?function fn() { return 20;}fn.tostring = function() { return 10;}fn.valueof = function() { return 5;}console.log(fn + 10); // 输出结果是多少?
16. 函数防抖和函数节流(es6)//函数节流const throttle = (fun, delay) => { let last = null; return () => { const now = + new date(); if (now - last > delay) { fun(); last = now; } }}//实例const throttleexample = throttle(() => console.log(1), 1000);//调用throttleexample();throttleexample();throttleexample();//函数防抖const debouce = (fun, delay) => { let timer = null; return () => { cleartimeout(timer); timer = settimeout(() => { fun(); }, delay); }}//实例const debouceexample = debouce(() => console.log(1), 1000);//调用debouceexample();debouceexample();debouceexample();
推荐教程:《js教程》
以上就是javascript容易被坑的问题的详细内容。