call、apply以及bind的介绍与基本应用

call方法

call方法可以修改函数运行时的this指向

fun.call (thisArg, arg1, arg2, ...)
  • thisArg:当前调用函数this的指向对象
  • arg1,arg2:传递的其他参数
// call 方法
function fn(x, y) {
    console.log('我想喝手磨咖啡');
    console.log(this);//fn默认指向的是window对象,但可以通过call方法改变this指向
    console.log(x + y);
}
var o = {
    name: 'andy'
};
// fn();
// 1. call() 可以调用函数
// fn.call();
// 2. call() 可以改变这个函数的this指向 此时这个函数的this 就指向了o这个对象,后面的参数当作正常的函数实参传递过去
fn.call(o, 1, 2);

call方法应用

一、借用构造函数继承父类型属性

核心原理:通过call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性。有点类似于ES6中的super

// 借用父构造函数继承属性
// 1. 父构造函数
function Father(uname, age) {
    // this 指向父构造函数的对象实例
    this.uname = uname;
    this.age = age;
}
// 2 .子构造函数 
function Son(uname, age, score) {
    // this 指向子构造函数的对象实例
    Father.call(this, uname, age);//继承了Father中的uname和age属性
    this.score = score;
}
var son = new Son('刘德华', 18, 100);
console.log(son);
二、通过call转换类数组为数组从而使用数组方法

获取DOM的方法返回的是类数组,不能使用forEach,push等数组的方法,为此可以通过使用下面的方法将类数组转换为真正的数组

// 直接获取DOM方法返回的是类数组
let lis = document.querySelectorAll('li');
console.log(lis)
// NodeList(4)[li, li, li, li]
// 0: li
// 1: li
// 2: li
// 3: li
// length: 4

// 可以使用下面的方法将类数组转换为普通数组
lis = Array.prototype.slice.call(document.querySelectorAll('li'))
console.log(lis)
// (4)[li, li, li, li]
// 0: li
// 1: li
// 2: li
// 3: li

apply方法

apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。

fun.apply(thisArg, [argsArray])
  • thisArg:在fun函数运行时指定的 this 值
  • argsArray:传递的值,必须包含在数组里面
  • 返回值就是函数的返回值,因为它就是调用函数
  • 因此 apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值
  1. apply方法会立马调用函数 可以改变函数内部的this指向
  2. 传入的第二个参数必须是数组(伪数组)
// 2. apply()  应用 运用的意思
var o = {
    name: 'andy'
};
function fn(arr) {
    console.log(this);
    console.log(arr); // 'pink'
};
fn.apply(o, ['pink']);
// 1. 也是调用函数 第二个可以改变函数内部的this指向
// 2. 但是他的参数必须是数组(伪数组)

apply方法的应用

一、借助于数学内置对象求数组最大值

例如Math.max.apply(null,list),其中list为一个数组,我们无法直接给max方法中传入一个数组,但是借用apply可以实现

// Math.max();
var arr = [1, 66, 3, 99, 4];
var arr1 = ['red', 'pink'];
// var max = Math.max.apply(null, arr);
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max, min);
二、实现两个数组合并

在 ES6 的扩展运算符出现之前,我们可以用 Array.prototype.push来实现。

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]

bind方法

语法

Function.bind(thisArg[, arg1[, arg2[, ...]]])

bind 方法 与 apply 和 call 比较类似,也能改变函数体内的 this 指向。不同的是,bind 方法的返回值是函数,并且需要稍后调用,才会执行。而 apply 和 call 则是立即调用。

function add (a, b) {
    return a + b;
}

function sub (a, b) {
    return a - b;
}

add.bind(sub, 5, 3); // 这时,并不会返回 8
add.bind(sub, 5, 3)(); // 调用后,返回 8

bind不会立即调用原来的函数,但是可以改变函数内部的this指向,返回改变this指向后的函数的拷贝

bind方法的应用

如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时可以用bind

例如我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮,因为setTimeout回调函数的this指向是windows,通过bind可以将this改成调用的那个按钮,这样可以实现在setTimeout里面开启按钮自身。

当需要改变this指针同时又要使用之前的this时,可以把之前的this指针作为参数传递过去
例如this.lis[i].onclick = this.toggleTab.bind(this.lis[i], this);

// bind()  绑定 捆绑的意思
var o = {
    name: 'andy'
};
function fn(a, b) {
    console.log(this);
    console.log(a + b);
};
var f = fn.bind(o, 1, 2);
f();
// 1. 不会调用原来的函数   可以改变原来函数内部的this 指向
// 2. 返回的是原函数改变this之后产生的新函数
// 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
// 4. 我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮
// var btn1 = document.querySelector('button');
// btn1.onclick = function() {
//     this.disabled = true; // 这个this 指向的是 btn 这个按钮
//     // var that = this;
//     setTimeout(function() {
//         // that.disabled = false; // 定时器函数里面的this 指向的是window
//         this.disabled = false; // 此时定时器函数里面的this 指向的是btn
//     }.bind(this), 3000); // 这个this 指向的是btn 这个对象
// }
var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
    btns[i].onclick = function() {
        this.disabled = true;
        setTimeout(function() {
            this.disabled = false;
        }.bind(this), 2000);
    }
}

call apply bind总结

相同点:都可以改变函数内部的this指向
区别点:

  1. call和 apply会调用函数并且改变函数内部this指向
  2. call和 apply传递的参数不一样,call传递参数aru1,aru2.形式 apply必须数组形式[arg]
  3. bind不会调用函数可以改变函数内部this指向

主要应用场景:

  1. call经常做继承
  2. apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值
  3. bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值