call、apply和bind的用法与说明

介绍

call、apply、bind的作用是改变函数运行时this的指向,欲了解函数,首先需知this

this

this到底是什个什么样的东西呢?

this即“这个”的意思,在代码中this指向调用函数的主体对象。


举个栗子:在一个代码中,例如:

var obj = {
  foo: function(){
    console.log(this)
  }
}
var bar = obj.foo
obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window

那么为什么会出现这种现象呢?这就得从函数的调用来说起了。
在 java script 中说起函数调用你首先想到的肯定是myFunction(a, b),厉害点的可能还会想到obj.objFunction()没错,这些都可以实现对函数调用,那么这些调用方式又有什么区别和联系呢?
首先我们先列举出来这些个调用方式

  • 作为一个函数进行调用myFunction(a, b)
  • 作为对象的一个方法进行调用obj.objFunction()
  • 使用构造函数调用let Bob = new Student('Bob', 18)
  • 作为函数的方法调用myFunction.call(context, a, b)

一般情况下,我们都习惯使用前几种方式,殊不知最后一种myFunction.call(context, a, b)才是正常的调用形式,其他几种都是语法糖,可以等价转换为此形式。

myFunction(a, b) 可等价于 myFunction.call(undefined, a, b)

obj.objFunction() 可等价于 obj.objFunction.call(obj)

这样来说this就好理解了,this其实就是以上式子中的context及call中的第一个参数。


注意:

如果你传的 context 是 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

call

call(打电话)可以实现函数与对象间的交流,使其具有联系

fun.call(context, arg1, arg2, ...)

  • 参数说明:
    • context :在 fun函数运行时指定的this值,当第一个参数为null、undefined的时候,默认指向window。
    • arg1, arg2:…指定的参数列表。
  • 返回值:
    使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined。

apply

与call相似,只是参数不同而已

fun.apply(context, arr)

  • 参数说明:
    • context :在 fun函数运行时指定的this值,当第一个参数为null、undefined的时候,默认指向window。
    • arr 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。

举栗子:将数组添加到另一个数组

let array = ['s', 'm', 'i', 'l', 'e']
let elements = [0, 1, 2]
array.push.apply(array, elements);
console.info(array); // ['s', 'm', 'i', 'l', 'e', 0, 1, 2]

既然callapply没多大区别,那么如何在两者间进行选择呢?

在参数杂乱无章,没有任何关联时建议使用call。如若参数存在一个数组中那么使用apply更加的合适

bind

bind会创建一个新绑定函数,它包装了原函数对象

fun.bind(context, arg1, arg2, ...)

  • 参数说明:
    • context :在 fun函数运行时指定的this值,当第一个参数为null、undefined的时候,默认指向window。
    • arg1, arg2:…指定的参数列表。
  • 返回值:
    返回一个原函数的拷贝,并拥有指定的this值和初始参数。

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数中的 this 并没有被改变,依旧指向全局对象 window

主要应用场景

  • 求数组中的最大和最小值
var arr = [1,2,3,4,5]
var max = Math.max.apply(null,arr)//5
var min = Math.min.apply(null,arr)//1
  • 数组追加
let array = ['s', 'm', 'i', 'l', 'e']
let elements = [0, 1, 2]
array.push.apply(array, elements);
// array['s', 'm', 'i', 'l', 'e', 0, 1, 2]
  • 判断变量类型
function isArray(obj){
  return Object.prototype.toString.call(obj) == '[object Array]';
}
isArray([]) // true
isArray('dcbryant') // false
  • 使用 log 代理 console.log
function log(){
  console.log.apply(console, arguments);
}
// 当然也有更方便的 var log = console.log()
  • 利用call和apply做继承
function Person(name,age){
  // 这里的this都指向实例
  this.name = name
  this.age = age
  this.sayAge = function(){
    console.log(this.age)
  }
}
function Female(){
  Person.apply(this,arguments)//将父元素所有方法在这里执行一遍就继承了
}
var dot = new Female('Dot',2)

参考

一次性讲清楚apply/call/bind

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值