call apply:
相同点:第一个参数是改变this指向,在非严格模式下传递null / undefined/不传参都是指向window
不同点::apply 需要的参数数组形式传递,call 一个一个传递 apply性能比call好
语法
fun.call([context],1,2)
fun.call([context],[1,2])
call和apply 与bind比较
区别:call和apply 都是改变this的同时把函数执行了,而bind不是立即执行函数,只是预先改变this
let obj={
fn(){
console.log(this)
}
}
obj.fn.call() //window
obj.fn.call('',1,2) //String {""}
obj.fn.apply('',[1,2]) //String {""}
call使用:
let a = {
name:"a",
Fna:function(param1,param2){
console.log(this.Fnb('a','b')); //this指向变成b,可调用b的方法Fnb
console.log(param1,param2,);//数据,call
}
}
let b = {
name:"b",
Fnb:function(param1,param2){
console.log(this);
console.log(param1,param2);//a,b
}
}
console.log(a.Fna.call(b,"数据","call"))//undefined
apply使用:
let a = {
name:"a",
Fna:function(param1,param2){
console.log(this.Fnb('a','b')); //this指向变成b,可调用b的方法Fnb
console.log(param1,param2,);//数据,call
}
}
let b = {
name:"b",
Fnb:function(param1,param2){
console.log(this);
console.log(param1,param2);//a,b
}
}
console.log(a.Fna.apply(b,["数据","call"]))//undefined
bind使用:
let a = {
name:"a",
Fna:function(param1,param2){
console.log(this.Fnb('a','b')); //this指向变成b,可调用b的方法Fnb
console.log(param1,param2,);//数据,call
}
}
let b = {
name:"b",
Fnb:function(param1,param2){
console.log(this);
console.log(param1,param2);//a,b
}
}
let c = a.Fna.bind(b);
console.log(c)//返回的函数
bind实现原理
~function anonymous(proto){
function bind(context,...agrs){
// arguments:{0:context,1:10,2:20,length:3}
if(context===undefined||context===null){ //undefined与==等于null
context=window
}
let _this=this
return function anonymous(...otherArgs){
_this.apply(context,agrs.concat(otherArgs))
}
}
proto.bind=bind
}(Function.prototype)
//简写apply
~function anonymous(proto){
function bind(context=window,...agrs){
return (...otherArgs)=>{
this.apply(context,agrs.concat(otherArgs))
}
}
proto.bind=bind
}(Function.prototype)
//简写用call
~function anonymous(proto){
function bind(context=window,...agrs){
return (...otherArgs)=>{
this.call(context,...agrs.concat(otherArgs))
}
}
proto.bind=bind
}(Function.prototype)
call原理
~function anonymous2(proto){
function call(context=window,...args){
context===null?context=window:null
let type=typeof context
if(type!=='object'&&type!=='function'&&type!=='symbol'){
switch(type){
case 'number': context=new Number(context); break;
case 'string': context=new String(context); break;
case 'boolean': context=new Boolean(context); break;
}
}
context.$fn=this
let result= context.$fn(...args)
delete context.$fn
return result
}
proto.call=call
}(Function.prototype)
apply原理
~function anonymous3(proto){
function apply(context=window,args){
context===null?context=window:null
let type=typeof context
if(type!=='object'&&type!=='function'&&type!=='symbol'){
switch(type){
case 'number': context=new Number(context); break;
case 'string': context=new String(context); break;
case 'boolean': context=new Boolean(context); break;
}
}
context.$fn=this
let result= context.$fn(...args)
delete context.$fn
return result
}
proto.apply=apply
}(Function.prototype)
题:
let obj={
fn(x,y,ev){
console.log(this,x,y,ev)
}
}
setTimeout(obj.fn.call(window,1,2),1000) //不等1秒执行执行
setTimeout(obj.fn.call(window,[1,2]),1000) //不等1秒执行执行
setTimeout(obj.fn.bind(window,1,2),1000) //一秒后在执行
document.body.onclick=obj.fn.bind(window,1,2)