在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转成真正的数组,之后就能够用数组的办法啦。