call、apply、bind的用法和区别

        在JavaScript中,call、apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。这也是这三个函数的共同点。

call()

语法:fun.call(thisArg, arg1, arg2, ...)
thisArg是在 fun函数运行时指定的 this值。arg1,arg2,...是底层调用fun方法传递的参数。

  • 如果第一个参数指定为 null和 undefined或者不传值,那么this值会自动指向全局对象(浏览器中就是window对象)
  • 如果第一个参数指定为数字、字符串或者布尔类型,那么this分别执行它们的包装对象
function fn() {
    console.log(this)
}
var obj = {
    name: '张三'
}
function show(){}
fn.call()   // Window
fn.call(null)   // Window
fn.call(undefined)  // Window
fn.call(1)  // Number
fn.call(false)  // Boolean
fn.call('嘿嘿') // String
fn.call(obj) // {name: "张三"}
fn.call(show)   // ƒ show(){}

举个简单的栗子来描述一下call方法吧:

function Animal(name) {
    this.name = name
    this.getName = function() {
        return this.name
    }
}

function Cat(name) {
    this.name = name
}

var animal = new Animal('动物')
var cat = new Cat('可爱的猫')
// console.log(cat.getName())  // TypeError: cat.getName is not a function
console.log(animal.getName.call(cat))   // 可爱的猫

animal这个对象是有getName这个方法的,这个方法有个this,这个this指向animal对象。但是我们用call方法可以把这个this指向cat,这个时候输出的就是cat的name啦。

apply()

语法:fun.apply(this,arguments)

apply和call方法的作用和使用方式几乎一样,除了参数不同。arguments是一个数组

function fn1(a,b,c) {
    this.getSum = function() {
        return a+b+c
    }
}

function fn2() {
    var a = 1
    var b = 5
    var c = 10
    fn1.apply(this,[a,b,c])
}
var f = new fn2()
console.log(f.getSum()) // 16

bind()

bind和apply以及call的区别在于:bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用。注意:bind方法的返回值是函数

function add(b,c) {
    return this.a+b+c
}
var bind = add.bind({a:1},2)
console.log(bind(3))    // 6

第一个参数是{a:1}所以,add函数的this指向{a:1}这个对象。第二个参数2赋值给b。这个时候并没有立即指向add方法,而是返回bind函数,我们要主动调一下bind函数才会执行add函数。此时调用bind函数的时候传的3会赋值给c,所以最终返回6

其实了解了这三个函数的用法之后,我比较纳闷的是实战中会用在什么地方,所以去搜索各类资料,总结出一些常用的场景。下面一一介绍

使用场景

1、求数组最大值最小值

let a = [35,3,67,23,67,38,64,89,34,46,23,56,78,43,34,56,67,34,65]
var min = Math.min.apply(null,a)
var max = Math.max.apply(null,a)
console.log(min,max)    // 3,89

Math.min()以及Math.max()的参数是不支持数组的,但是apply方法是支持数组的。并且apply的数组参数在底层会展开一个一个给max方法,这样就能很轻松的实现求数组最大最小值。其中apply 的第一个参数是null是因为没有对象去调这个方法,我们只要用这个方法帮我们完成运算得到返回值就行

2、实现两个数组合并

var arr1 = [1,2,3]
var arr2 = ['a','b','c']
Array.prototype.push.apply(arr1,arr2)
console.log(arr1)   // [1, 2, 3, "a", "b", "c"]
console.log(arr2)   // ["a", "b", "c"]

Array的push方法也是没有提供push数组的。但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来转换一下这个数组

3、继承

function Animal(name) {
    this.name = name
    this.getName = function() {
        return this.name
    }
}
Animal.prototype.age = 18
function Dog(name) {
    Animal.call(this,name)
    // Animal.apply(this,[name])
    // Animal.bind(this,name)()
}

var dog = new Dog('小狗')
console.log(dog.getName())  // 小狗

Dog构造函数是没有getName方法的,但是通过改变this指向,Animal里的this指向Dog里的this,这样就实现继承啦

4、伪数组使用数组方法

var lis = document.querySelector('ul').childNodes
console.log(lis)
// lis.slice(0,1) TypeError: lis.slice is not a function
Array.prototype.slice.call(lis,0,1)

getElementsByTagName , document.childNodes等方法返回的对象都属于伪数组,伪数组是不能使用数组的方法的,所以我们可以用call转成真正的数组,之后就可以用数组的方法啦

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值