前言
题目来自Daily-Interview-Question 木易杨
欢迎star,加入讨论
本文记录自己对题目的解决方式以及综合大神们的看法。
题目
1、请写出如下代码的打印结果
var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
答案:
Goodbye Jack
题目变形:
ldlcoder给出了题目变形,将var name = 'Jack'
变成了let name = 'Jack'
var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
let name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
答案:
Hello Tom
理由:
我自己的理解:
var 声明的变量没有块作用域,也就是说会有变量提升,提升到function作用域的最上层,只是声明了变量,但是没有赋值,所以是undefined。
let存在暂时性死区,不会有变量提升,也就是说function一开始是找不到name这个变量的,然后他会去外层找name,一直找到window下name这个变量,得到typeof name === 'string'
,打印Hello Tom
2、什么是防抖和节流?有什么区别?如何实现?
答案:
防抖
我觉得这篇文章讲的不错
节流
JavaScript专题之跟着 underscore 学节流
例如说:
有一个按钮点击会触发网络请求,但是我们并不希望每次点击都发起网络请求,而是当用户点击按钮一段时间后没有再次点击的情况才去发起网络请求,对于这种情况我们就可以使用防抖。
滚动事件中需要做个复杂计算。
鼠标移动时频繁触发事件的时候。
...
防抖
在这篇文章里 JavaScript专题之跟着underscore学防抖
给出的防抖函数
最初版:
function debounce(func, wait) {
var timeout
return function () {
//清除计时器
clearTimeout(timeout)
//延迟一段时间执行
timeout = setTimeout(func, wait)
}
}
function getUserAction() {
container.innerHTML = count++
}
//鼠标滑过的过程中不触发,执行完最后一次滑动事件时,一秒钟之后执行一次
container.mousemove = debouce(getUserAction, 1000)
修正this指向
这里apply返回的是调用有指定this值和参数的函数的结果。
Function.prototype.apply() MDN
所以要用function包起来
function debounce(func,wait) {
var timeout
return function(){
var context = this
//清除计时器
clearTimeout(timeout)
//延迟一段时间执行
timeout = setTimeout(function(){
func.apply(context)
}, wait)
}
}
传入event对象
function debounce(func,wait) {
var timeout
return function(){
var context = this
var args = arguments
//清除计时器
clearTimeout(timeout)
//延迟一段时间执行
timeout = setTimeout(function(){
func.apply(context, args)
}, wait)
}
}
加入立即执行的效果
function debounce(func, wait, immediate) {
var timeout
return function () {
var context = this
var args = arguments
if (timeout) clearTimeout(timeout)
if (immediate) {
/*timeout这个变量一开始是undefined,所以callNow为true
这个时候开始到if(callNow)这条语句,调用了func.apply,使innerHTML+1
等待wait毫秒之后,返回timeout为null,又触发func.apply达到立即执行的目的
*/
var callNow = !timeout
timeout = setTimeout(function(){
timeout = null
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait)
}
}
}
节流
JavaScript专题之跟着 underscore 学节流
防抖和节流不一样,防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
关于节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。
先写一版时间戳的方法
其中+new Date()
相当于ToNumber(new Date())
// 第一版
function throttle(func, wait) {
var context, args;
var previous = 0;
return function() {
var now = +new Date();
context = this;
args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
var count = 1;
var container = document.getElementById('container');
function getUserAction() {
container.innerHTML = count++;
};
container.onmousemove = throttle(getUserAction, 1000);
未完待续