call、apply、bind 的用法

219 阅读1分钟

1.call

js中有主要有三种函数调用方法

func(p1, p2) 
func.call(context, p1, p2)
obj.child.method(p1, p2)

带call的调用才是正常的、高级的调用方式。同时call与this是分不开的,下面举例讲解this与call的用法。

js函数调用可以等价为call形式:

func.call(context, p1, p2)

this,就是上面代码中的 context。

let  obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};  
//////////////////////////////////////////////
let  obj2 = {
  foo: function () { console.log(this.bar) },
  bar: 3
};
//////////////////////////////////////////////
let foo = obj.foo;
let bar = 2;
////////////////////////////////////////////
obj.foo() // 调用1,结果为1
foo() // 调用2,结果为2

转换为call调用:

  • 调用1:等价于obj.foo.call(obj),this就是obj,obj.bar=1
  • 调用2:等价于foo.call(undefined),也就是context为undefined,但是浏览器里有一条规则,如果context 是 null 或 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined),故window.bar=2。

或者你也可以这样理解:

  • obj.foo()是通过obj找到foo,所以就是在obj环境执行,obj.bar=1。
  • let foo = obj.foo,变量foo就直接指向函数本身,所以foo()就变成在全局环境执行,window.bar=2。

另外,如果你想改变this,可以这样:

obj.foo.call(obj2)

this,就变成了obj2。
由此,函数的调用可以转换为call方式:

func(p1, p2) 等价于
func.call(undefined, p1, p2)
///////////////////////////////////////////////
obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)

2.apply

fn.apply(context,[p1,p2])

apply后面参数要以数组的形式传递,其他与call用法相同。

3.bind

bind可以绑定this。

function f1(p1,p2){console.log(this,p1,p2)}
let f2=f1.bind({name:'frank'})

那么,this就绑定为了{name:'frank'},f2(p1,p2)等价于f1.call({name:'frank'},p1,p2) bind也可以绑定其他参数

let f3=f1.bind({name:'frank'},'hi')

那么f3(p1,p2)等价于f1.call({name:'frank'},hi,p1,p2)