1. 如何封装一个 javascript 的类型判断函数?

function getType(value) {
// 判断数据是 null 的情况
if (value === null) {
return value + "";
}

// 判断数据是引用类型的情况
if (typeof value === "object") {
let valueClass = Object.prototype.toString.call(value),
type = valueClass.split(" ")[1].split("");

type.pop();

return type.join("").toLowerCase();
} else {
// 判断数据是基本数据类型的情况和函数的情况
return typeof value;
}
}


2. 如何判断一个对象是否为空对象?

function checkNullObj(obj) {
return Object.keys(obj).length === 0 && Object.getOwnPropertySymbols(obj).length === 0;
}


详细资料可以参考:

《js 判断一个 object 对象是否为空》

3. 使用闭包实现每隔一秒打印 1,2,3,4

// 使用闭包实现
for (var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
console.log(i);
}, i * 1000);
})(i);
}


// 使用 let 块级作用域
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, i * 1000);
}


4. 一道常被人轻视的前端 JS 面试题

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(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3


5. 为什么使用 setTimeout 实现 setInterval?怎么模拟?

相关知识点:

// 思路是使用递归函数,不断地去执行 setTimeout 从而达到 setInterval 的效果

function mySetInterval(fn, timeout) {
// 控制器,控制定时器是否继续执行
var timer = {
flag: true
};

// 设置递归函数,模拟定时器执行。
function interval() {
if (timer.flag) {
fn();
setTimeout(interval, timeout);
}
}

// 启动定时器
setTimeout(interval, timeout);

// 返回控制器
return timer;
}


回答:

setInterval 的作用是每隔一段指定时间执行一个函数,但是这个执行不是真的到了时间立即执行,它真正的作用是每隔一段时间将事件加入事件队列中去,只有当当前的执行栈为空的时候,才能去从事件队列中取出事件执行。所以可能会出现这样的情况,就是当前执行栈执行的时间很长,导致事件队列里边积累多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此就不能到间隔一段时间执行的效果。

针对 setInterval 的这个缺点,我们可以使用 setTimeout 递归调用来模拟 setInterval,这样我们就确保了只有一个事件结束了,我们才会触发下一个定时器事件,这样解决了 setInterval 的问题。


详细资料可以参考:

​《用 setTimeout 实现 setInterval》​

​《setInterval 有什么缺点?》​

6. 如何查找一篇英文文章中出现频率最高的单词?

function findMostWord(article) {
// 合法性判断
if (!article) return;

// 参数处理
article = article.trim().toLowerCase();

let wordList = article.match(/[a-z]+/g),
visited = [],
maxNum = 0,
maxWord = "";

article = " " + wordList.join(" ") + " ";

// 遍历判断单词出现次数
wordList.forEach(function(item) {
if (visited.indexOf(item) < 0) {

// 加入 visited
visited.push(item);

let word = new RegExp(" " + item + " ", "g"),
num = article.match(word).length;

if (num > maxNum) {
maxNum = num;
maxWord = item;
}
}
});

return maxWord + " " + maxNum;
}