1.以下递归函数存在栈溢出的风险,请问如何优化?
function factorial(n){
return n*factorial(n-1)
}
解答:
function factorial(n){ if(n === 1) { return 1;}; return n*factorial(n-1) }
2.请实现一个计算最大公约数的函数:
function greatestCommonDivisor(a,b){
//在这里编写代码
}
greatestCommonDivisor(8, 12) //4
greatestCommonDivisor(8, 16) //8
greatestCommonDivisor(8, 17) //1
解答:
function greatestCommonDivisor(a,b){ var num=0; while(b!=0){ num=a%b; a=b; b=num; } return a; }
3.数组去重(如果数组中有NaN)
Array.prototype.uniq = function () { var resArr = []; var flag = true; for(var i=0;i<this.length;i++){ if(resArr.indexOf(this[i]) == -1){ if(this[i] != this[i]){
//排除 NaN if(flag){ resArr.push(this[i]); flag = false; } }else{ resArr.push(this[i]); } } } return resArr; }
4.用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等
function fibonacci(n) { if(n ==1 || n == 2){ return 1 } return fibonacci(n - 1) + fibonacci(n - 2); }
5.根据包名,在指定空间中创建对象
输入描述:
namespace({a: {test: 1, b: 2}}, 'a.b.c.d')
输出描述:
{a: {test: 1, b: {c: {d: {}}}}}
function namespace(oNamespace, sPackage) { var properties = sPackage.split('.'); var parent = oNamespace; for (var i = 0, lng = properties.length; i < lng; ++i) { var property = properties[i]; if (Object.prototype.toString.call(parent[property])!== '[object Object]') { parent[property] = {}; } parent = parent[property]; } return oNamespace; }
6.封装函数 f,使 f 的 this 指向指定的对象
function bindThis(f, oTarget) { return function(){ var parames = Array.prototype.slice.call(arguments); return f.apply(oTarget,parames); //注意这里需要返回f的执行结果 } }
7.dom 节点查找
查找两个节点的最近的一个共同父节点,可以包括节点自身
输入描述:
oNode1 和 oNode2 在同一文档中,且不会为相同的节点
function commonParentNode(oNode1, oNode2) { if(oNode1.contains(oNode2)){ return oNode1; }else if(oNode2.contains(oNode1)){ return oNode2; }else{ return commonParentNode(oNode1.parentNode,oNode2); } }
8.关系型数组转换成树形结构对象
关系型数组
var obj = [ { id:3, parent:2 }, { id:1, parent:null }, { id:2, parent:1 }, ]
期望结果:
o = { obj: { id: 1, parent: null, child: { id: 2, parent: 1, child: { id: ,3, parent: 2 } } } }
实现源码:
function treeObj(obj) { obj.map(item => { if (item.parent !== null) { obj.map(o => { if (item.parent === o.id) { if (!o.child) { o.child = []; } o.child.push(item); o.child = o.child; } }); } }); return obj.filter(item => item.parent === null)[0] }
或者:
function treeObj(obj) { return obj.sort((a, b) => b.parent - a.parent) .reduce((acc, cur) => (acc ? { ...cur, child: acc } : cur)); }
9.JS如何判断一组数字是否连续
// 当出现连续数字的时候以‘-’输出 [1, 2, 3, 4, 6, 8, 9, 10]
期望结果::
["1-4", 6, "8-10"]
实现代码:
判断是否连续:
var arrange = function(arr){ var result = [],temp = []; arr.sort(function(source, dest){ return source - dest; }).concat(Infinity).reduce(function(source, dest){ temp.push(source); if(dest-source > 1){ result.push(temp); temp = []; } return dest; }); return result; };
格式化实现:
var formatarr = function(arr) { var newArr = [] var arr1 = arrange(arr) for (var i in arr1) { var str = ''; if (arr1[i].length > 1) { str = arr1[i][0] + '-' + arr1[i][arr1[i].length - 1]; newArr.push(str) } else { newArr.push(arr1[i][0]); } } return newArr; }
10.创建子类Child,使用原型和构造函数的方式继承父类People的方法,并调用say函数说出姓名和年龄。
父类:
function People(name,age){ this.name=name; this.age=age; this.say=function(){ console.log("我的名字是:"+this.name+"我今年"+this.age+"岁!"); }; }
原型继承:
function Child(name, age){ this.name = name; this.age = age; } Child.prototype = new People(); var child = new Child('Rainy', 20); child.say()
构造函数继承:
function Child(name, age){ People.call(this) this.name = name; this.age = age; } var child = new Child('Rainy', 20); child.say()
组合继承:
function Child(name, age){ People.call(this); this.name = name; this.age = age; } Child.prototype = People.prototype; var child = new Child('Rainy', 20); child.say()
组合继承优化:
function Child(name, age){ People.call(this); this.name = name; this.age = age; } Child.prototype = Object.create(People.prototype); Child.prototype.constructor = Child; var child = new Child('Rainy', 20); child.say()