前端强化 (六月)

160 阅读2分钟

1.闭包

闭包是指有权访问另外一个函数作用域中的变量的函数,主要是下面两点:

  • 是一个函数
  • 能访问另外一个函数作用域中的变量

函数柯里化

// 木易杨
const add = (...args) => args.reduce((a, b) => a + b);

// 简化写法
function currying(func) {
    const args = [];
    return function result(...rest) {
        if (rest.length === 0) {
          return func(...args);
        } else {
          args.push(...rest);
        	return result;
        }
    }
}

const sum = currying(add);

sum(1,2)(3); // 未真正求值
sum(4); 		 // 未真正求值
sum(); 			 // 输出 10

2. EventLoop

<!--1-->
setImmediate(() => {
  console.log('setImmediate1')
  setImmediate(() => {
    console.log('setImmediate2')
  })
  process.nextTick(() => {
    console.log('nextTick')
  })
})

setImmediate(() => {
  console.log('setImmediate3')
})
输出:
setImmediate1
setImmediate3
nextTick
setImmediate2
<!--2-->
setImmediate(() => {
  console.log(1)
  setTimeout(() => {
    console.log(2)
  }, 100)
  setImmediate(() => {
    console.log(3)
  })
  process.nextTick(() => {
    console.log(4)
  })
})
process.nextTick(() => {
  console.log(5)
  setTimeout(() => {
    console.log(6)
  }, 100)
  setImmediate(() => {
    console.log(7)
  })
  process.nextTick(() => {
    console.log(8)
  })
})
console.log(9)
输出:
9
5
8
1
7
4
3
6
2

3. 经典js new 面试题(注意后三个运算优先级)

new (带参数列表)优先级大于new (无参数列表)

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)(); 所以这里实际上将getName函数作为了构造函数来执行
new Foo().getName();//3 (new Foo()).getName() 首先new有参数列表(18)跟点的优先级(18)是同级,同级的话按照从左向右的执行顺序,所以先执行new有参数列表(18)再执行点的优先级(18),最后再函数调用(17)
new new Foo().getName();//3 new ((new Foo()).getName)(); 先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new,所以最终结果为3

4. 函数节流

window.onresize = throttleV2(myFunc, 50, 100);则意味着,50ms的间隔内连续触发的调用,后一个调用会把前一个调用的等待处理掉,但每隔100ms至少执行一次。原理也很简单,打时间tag,一开始记录第一次调用的时间戳,然后每次调用函数都去拿最新的时间跟记录时间比,超出给定的时间就执行一次,更新记录时间。


var throttleV2 = function(fn, delay, mustRunDelay){
 	var timer = null;
 	var t_start;
 	return function(){
 		var context = this, args = arguments, t_curr = +new Date();
 		clearTimeout(timer);
 		if(!t_start){
 			t_start = t_curr;
 		}
 		if(t_curr - t_start >= mustRunDelay){
 			fn.apply(context, args);
 			t_start = t_curr;
 		}
 		else {
 			timer = setTimeout(function(){
 				fn.apply(context, args);
 			}, delay);
 		}
 	};
 };

window.onresize = throttleV2(myFunc, 50, 100);