1、call,apply和bind
call和apply可以调用函数,改变this,实现继承和借用别的对象的方法;
1.1 call和apply用法
- 间接调用函数,改变作用域的this值
- 劫持其他对象的方法
var foo = {
name:"张三",
logName:function(){
console.log(this.name);
}
}
var bar={
name:"李四"
};
foo.logName.call(bar);//李四
// 实质是call改变了foo的this指向为bar,并调用该函数
- 两个函数实现继承
function Animal(name){
this.name = name;
this.showName = function(){
console.log(this.name);
}
}
function Cat(name){
Animal.call(this, name);
}
var cat = new Cat("Black Cat");
cat.showName(); //Black Cat
- 为类数组(arguments和nodeList)添加数组方法push,pop
(function(){
Array.prototype.push.call(arguments,'王五');
console.log(arguments);//['张三','李四','王五']
})('张三','李四')
- 合并数组
let arr1=[1,2,3];
let arr2=[4,5,6];
Array.prototype.push.apply(arr1,arr2); //将arr2合并到了arr1中
- 求数组最大值
Math.max.apply(null,arr)
- 判断数据类型(这种方式比较常用)
Object.prototype.toString.call({})
1.2 bind
bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,例如,f.bind(obj),实际上可以理解为obj.f(),这时,f函数体内的this自然指向的是obj。
详解:bind方法
this.name = "test";
let testObj = {
name:'zhangsan',
introduce:function(){
return this.name;
}
}
let test = {
name:"lisi"
}
let test1 = {
name:"wangwu"
}
let fn = testObj.introduce;
console.log(fn());//test
console.log(fn.bind(test)());//lisi
console.log(fn.bind(test1)());//王五
1.3 三者异同
- 同:都是改变this指向,都可接收参数
- 异:bind和call是接收单个参数,apply是接收数组
2、函数的节流和防抖
2.1 节流
- 概念:事件触发后每隔一段时间触发一次,可触发多次
- 应用:scroll,resize事件一段时间触发多次
// 节流函数
let throttle = function(func, delay) {
let timer = null;
return function() {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, arguments);
// 或者直接 func()
timer = null;
}, delay);
}
};
};
// 处理函数
function handle() {
console.log(arguments);
console.log(Math.random());
}
// 测试用例
document
.getElementsByClassName("scroll-box")[0]
.addEventListener("scroll", throttle(handle, 3000));
2.2 防抖
- 概念:事件触发动作完成后一段时间触发一次
- 应用:scroll,resize事件触发完后一段时间触发
// 防抖函数
let debounce = function(fn, wait) {
let timeout = null;
return function() {
if (timeout !== null) clearTimeout(timeout); //如果多次触发将上次记录延迟清除掉
timeout = setTimeout(() =