call()、apply()、bind()详解,在 JavaScript 中,this 是指当前函数中正在执行的上下文环境;当你调用一个函数时,this总是作为一个(隐式)参数。
(1)、宽松模式下的普通函数:
this总是指向全局对象,(在浏览器中是window)
var a=123; var A=function(){ return this; //Window }
(2)、严格模式下
使用严格模式,只需要将 ‘use strict’ 置于函数体的顶部。this总是undefined;
var a=123; var A=function(){ 'use strict'; return this; //undefined }
(3)方法
this指向调用方法的对象
var qwe={ method:function(){ return this; } } console.log(qwe.method()===qwe) ; //true
在讲call()之前先说一下,函数调用有4中类型:
函数调用 alert('Hello World!') 方法调用 console.log('Hello World!') 构造函数调用 new RegExp('\\d') 间接调用 alert.call(undefined, 'Hello World')
注意:this 是指当前函数中正在执行的上下文环境
陷阱:this 在内部函数中
一个常见的陷阱是理所应当的认为函数调用中的,内部函数中 this 等同于它的外部函数中的 this。
正确的理解是内部函数的上下文环境取决于调用环境,而不是外部函数的上下文环境。
为了获取到所期望的 this,应该利用间接调用修改内部函数的上下文环境,如使用 .call() 或者 .apply或者创建一个绑定函数 .bind()。
利用call、apply、bind这三个方法,可以改变this的指向,使它指向我们期望的对象。
一、call()
关于javascript中的call方法,总结网上的观点,call有两个妙用:
1: 修改函数运行时的this指针。
2: 继承。(不太喜欢这种继承方式。)
简单说明一下
var f=function(){} f.call(o)
解释:一个简单的例子,在全局环境下创建一个变量f,在函数f里面的this指向全局,window;但是利用call方法,将this指向了对象o,在o的作用域中运行函数f。
1、call()的完整使用格式:
func.call(thisValue, arg1, arg2, ...)
第一个参数是this要重新指向的那个对象,后面的参数是调用时所需要的参数;
或者是:
Function.prototype.call(thisValue, arg1, arg2, ...)
说明 :
call 方法可以用来代替另一个对象调用一个方法。
obj1.method1.call(obj2,argument1,argument2)
如上,call的作用就是把obj1的方法method1放到obj2上使用,后面的argument1..这些做为参数传入。
简单例子如下:
function one1(a,b){ console.log(a+b); }; function two1(a,b){ console.log(a-b); }; one1.call(two1,5,2); //7
这个例子中的意思就是用 one1来替换 two1,所以运行结果为:7
// 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。
看个稍微复杂的例子:
function duixiang1(){ this.name="zyy"; this.method=function(){ return this.name; } }; function duixiang2(){ this.name="zxd"; } var q1=new duixiang1(); var q2=new duixiang2(); console.log(q1.method()); //zyy console.log(q1.method.call(q2)); //zxd
解释:call 的意思是把 q1的方法放到q2上执行,原来q2是没有method() 方法,现在是把q1 的method()方法放到 q2 上来执行,所以this.name 应该是 zxd,执行的结果就是 :zxd;
有意思吧,可以让a对象来执行b对象的方法。还有更有趣的,可以用 call 来实现继承 :
接下来说明一下call()实现继承:
function Class1(){ this.name="abc"; this.method=function(a){ console.log("这是Class1的参数"+a); } }; function Class2(){ Class1.call(this); // this.name="qwe" } var newclass2=new Class2(); newclass2.method("asd"); //这是Class1的参数asd
这样 Class2 就继承Class1了,Class1.call(this) 的 意思就是使用 this对象代替Class1对象调用Class1的方法,那么 Class2 中不就有Class1 的所有属性和方法了吗,Class1对象就能够直接调用Class1 的方法以及属性了,执行结果就是:alert(“cc”);
对的,就是这样,这就是 javascript 如何来模拟面向对象中的继承的,还可以实现多重继承。
function Ff1(){ this.methodadd=function(a,b){ console.log(a+b) } }; function Ff2(){ this.methodjian=function(a,b){ console.log(a-b); } }; function Ff3(){ Ff1.call(this); Ff2.call(this); }; var shili=new Ff3(); shili.methodadd(2,2); //4 shili.methodjian(5,4); //1
很简单,使用两个 call 就实现多重继承了 。