call、apply、bind
1、相同也不同
我们先从浅显的部分开始讲,
这三个方法都可以改变this的指向,都可以进行传参,第一个参数都是修改this的指向
call() 和 apply() 改变this指向后会立即执行函数
bind() 改变this指向后不会立即执行
call() 和 apply() 区别在于参数
· call() 第一个参数是修改的this指向,后续的参数都是传入该函数的值,他的传值只能一个个传
· apply() 第一个参数是修改的this指向,第二个参数是一个数组,所有传入该函数的值都放到该数组中
javaScript权威指南上的解释是:
call() 、apply()可以看作是某个对象的方法,
通过调用方法的形式来间接调用函数。
bind() 就是将某个函数绑定到某个对象上。
2、照常举🌰
复制代码
var boy = {
name : "李雷",
gender : "男",
age : 17,
say : function() {
alert(this.name + " , " + this.gender + " ,今年" + this.age);
}
}
var girl = {
name : "韩梅梅",
gender : "女",
age : 16
}
boy.say();
复制代码
此时弹出的内容是:
李雷,男,今年17
那么如果我们想输出girl这个对象的数据怎么办,
换种说法就是,
在只改变这个代码最后一句话的情况下怎么让girl对象拥有say这个方法?
复制代码
//对于call
boy.say.call(girl);
//对于apply
boy.say.apply(girl);
//对于bind
boy.say.bind(girl)();
复制代码
由此可以看出:
call() 和 apply() 改变this指向后会立即执行函数,
bind方法返回的仍然是一个函数需要调用才会执行
此时我们把🌰换成需要传递参数的:
复制代码
var boy = {
name : "李雷",
gender : "男",
age : 17,
say : function(mes1,mes2) {
alert(this.name + " , " + mes1 + mes2);
}
}
var girl = {
name : "韩梅梅",
gender : "女",
age : 16
}
boy.say("喜欢","韩梅梅");
//此时输出:李雷,喜欢韩梅梅
//call
boy.say.call(girl,"也喜欢","自己")
//apply
boy.say.apply(girl,["也喜欢","自己"])
//bind
boy.say.bind(girl,"也喜欢","自己")()
复制代码
3、如何自己写一个call方法呢?
思路:call方法的思路是改变this的指向,让新的对象可以执行该函数,
那么思路是否可以变为给新的对象添加一个函数,
执行后再删除呢?
复制代码
//自定义一个myCall方法挂载到Function通过prototype实现公共方法
Function.prototype.myCall = function (context) {
//context是obj2,因为只获取了第一个参数
//与call方法一样,context中第一个为新的this的指向
//剩下的部分为传入的参数
//此处是如果没传this指向的话就指向window
var context = context || window
//此处的this指向调用myCall的函数,就是你定义的初始对象的函数
//此处对应的this就是obj1.fn
context.fn = this
//获取除了this指向其余的参数
var args = [...arguments].slice(1)
//指向函数并把参数传进去
var result = context.fn(...args)
//删除该方法
delete context.fn
return result
}
var obj1 = {
name:'name1',
fn:function(mes){
console.log(this.name+mes)
}
}
var obj2 = {
name:"name2"
}
obj1.fn.myCall(obj2,"111")
//输出name2111
复制代码
4、如何自己写一个apply方法呢?
复制代码
//整体与call没什么太大的区别
//那我们就主要看看区别
//区别就在于是否需要传参
//因为他的参数全都在数组里
Function.prototype.myApply = function (context) {
var context = context || window
context.fn = this
var result
// 需要判断是否存储第二个参数
// 如果存在,就将第二个参数展开
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
复制代码
5、如何自己写一个bind方法呢?
复制代码
Function.prototype.myBind = function (context) {
var _this = this
var args = [...arguments].slice(1)
// 返回一个函数
return function () {
return _this.apply(context, args.concat(...arguments))
}
}
复制代码https://www.cnblogs.com/yangyangxxb/p/10124788.html