共计 2609 个字符,预计需要花费 7 分钟才能阅读完成。
在 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 转成真正的数组,之后就能够用数组的办法啦。