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)