前几天所里招聘React前端,由我来负责笔试。为防止有人背题,笔试后要询问应聘者答题思路,因此我提前做了这套笔试题。下面是节选的部分原题。
第一题:
(function(){ return typeof arguments; })();
思路:关键字arguments返回函数传入的参数,是object。因此return的是object。
第二题:
(function(x){ delete x; return x; })(1);
思路:结果为1,delete无法删除元素。delete用于删除对象中的某些属性,如delete person.name将name属性从对象person中去除。此外,Map、Set中也使用delete删除元素,不同的是Map中传入key,Set中传入自身。
第三题:
var y = 1, x = y = typeof x; console.log(x);
思路:参考千万不要在JS中使用连等赋值操作,A=B=C等同B=C,A=B。先看y = typeof x,x此时未赋值,因此是undefined,此时y被赋值为undefined。之后x = y,x被赋值为undefined。
补充:赛码网上去年360笔试题中有一题与本题很像。
var a,b; (function(){ console.log(a); console.log(b); var a=b=3; console.log(a); console.log(b); })(); console.log(a); console.log(b);思路:立即执行函数中var a=b=3可分解为b=3,var a=b。由于b前没有var重新声明,因此是全局变量b被赋值3,之后函数内局部变量a被赋值3。第一对console.log输出的a是局部变量a,b是全局变量b,两者都未定义。第三对console.log输出的是全局变量a,b。因此结果为:undefined,undefined,3,3,undefined,3。
第四题:
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0](); })(foo.bar);
思路:foo.bar是function,因此将foo.bar传入并执行h后相当于return typeof this.baz。由于当前object没有baz这个属性,因此返回undefined。
第五题:
var m= 1, j = k = 0; function add(n) { return n = n+1; } y = add(m); function add(n) { return n = n + 3; } z = add(m);
y和z的最终结果为4,4。js解释器会在所有代码执行前先查找所有函数,因此可以在函数声明前调用函数。并且后面定义的函数将覆盖前面同名的函数(即使调用参数不同)。实验如下。
dosth(); dosth(2); function dosth(num){ console.log(num); } function dosth(){ console.log('1'); }
打印1,1,说明后面的dosth覆盖了前面的dosth。另外,python在调用函数前必须先声明函数,而且函数会根据位置发生重载。
第六题:
var a = {n:1}; var b = a; a.x = a = {n:2}; console.log(a.x); console.log(b.x);
思路:结果为undefined,{n:2}。js赋值操作先获得左侧地址,再计算右侧结果赋值到左边。首先a,b都指向对象{n:1},第三行先取得{n:1}对象,取得{n:1}.x地址,之后计算右边,将a赋值为对象{n:2}。之后打印a.x的a是{n:2},没有a.x;打印b.x的对象是{n:1,x:{n:2}}。经过测试,python中使用字典也是同样的结果,说明python也是先去左边地址,再计算右边结果。
第七题:
let xx = function () { console.log("done"); }(); console.log(xx);//undefined
思路:将xx赋值为一个立即执行函数,无返回值,因此是undefined。
编程题1:只用一重循环去掉一组整型数组中重复的值。比如输入: [1,13,24,11,11,14,1,2],输出: [1,13,24,11,14,2],需要去掉重复的11和1这两个元素。
function unique(arr){ let hash={}; let data=[]; for (let i=0;i<arr.length;i++){ if (!hash[arr[i]]) { hash[arr[i]]=true; data.push(arr[i]); } } return data }
思路:最简单的方法是建一个表,记录每一个元素是否出现,返回未重复出现的元素。
function unique(arr){ return arr.filter(function(element, index, self){ if(self.indexOf(element)===index) return true; else return false; }); }
改进:可使用arr.filter()传入函数,若indexOf返回值与本身index相等,则返回true,保留,否则返回false,删去。
编程题2:输出一个数组里可以组成三角形的方案个数。输入数组已由小到大排序比如输入: [1,2,3,4,5],可组成三角形[2,3,4],[2,4,5],[3,4,5],因此输出: 3。
思路:最简单的方法是暴力枚举。假设传入数组为arr,最外层循环遍历整个数组,取一条最短边;第二层循环从i+1开始取,取中间长度的边;最内层循环从j+1开始取,取最长边。之后判断两边之和大于第三边,两边之差小于第三边即可。
var arr=[1, 2, 3, 4, 5]; var count=0; for (let i=0;i<arr.length-2;i++) { for(let j=i+1;j<arr.length-1;j++){ for(let k=j+1;k<arr.length;k++){ if(arr[i]+arr[j]>arr[k]){ count++; } } } } console.log(count);改进:在此基础上可以进行改进,加一些剪枝条件。如i=1,j=2,此时k会取3、4、5三个值,当k取3时,已经不满足两边之和大于第三边条件,因为数组升序,后面可不用遍历。