JavaScript中若想改变this的指向那就必须用到apply call bind 方法,但其中三个方法有他们的区别
apply()
apply():第一个参数将代替function类里的this对象,第二个参数是数组,将他作为参数传给function的arguments
function a(){
this.name = 'a';
this.show = function(){alert(this.name)};
}
function b() {
this.name = 'b';
}
var B = new b();
a.apply(B);
B.show();
这时输出a,这是因为apply方法中将this的指针改为了b,在function中b.name = 'a', b.show = function(){alert(this.name)};所以当再次调用B.show()时输出的是a
function A(a,b) {
this.a = a;
this.b = b;
}
function B() {
A.apply(this,[1,2]);
this.c = 3;
}
var s = new B();
alert(s.a+","+s.b+","+s.c);
这时输出1,2,3,这是因为在B函数中用apply方法将B的this给了a的this,将后面的1,2作为参数传给了A,这时给B的this分别添加了a和b属性,所以再次输出的时候B中会存在a,b,c三种属性。
call ()
call():call方法和apply方法类似只不过传入参数方法不同call方法中第二个参数不是数组,而是从第二个开始其余参数直接传给函数的arguments
,f function a(){
this.name = 'a';
this.show = function(){alert(this.name)};
}
function b() {
this.name = 'b';
}
var B = new b();
a.call(B);
B.show();
在这里我们将之前的apply方法改为了call方法,执行之后的结果和方法与apply方法相同
function A(a,b) {
this.a = a;
this.b = b;
}
function B() {
A.call(this,1,2);
this.c = 3;
}
var s = new B();
alert(s.a+","+s.b+","+s.c);
在这里我们将B函数中的apply方法改为了call方法,执行之后的结果和方法与apply方法相同,但是在这里call方法传入的参数发生了变化,apply是传入数组,而call方法是直接将参数传入
有了之前的铺垫,那么我们现在继续深入一下
function A(a,b) {
this.a = a;
this.b = b;
}
function B() {
this.a = 5;
this.c = 3;
A.call(this,1,2);
}
var s = new B();
alert(s.a+","+s.b+","+s.c);
这时大家猜测一下输出是什么,是5,2,3吗?
不,这时继续输出1,2,3,为什么呢?这时因为给B调用了A的call方法,使A的this指针指向了B,虽然我们定义了B的a为5,但是在调用call方法之后又将B的a重写为了1
function A(){
this.show = function(){alert(this.name)}
}
function B(){
this.name = 'b';
}
var C = new A();
var D = new B();
C.show.call(D);
alert(D.show);
这段代码中,让C.show中的this指向了D,但是并没有给D写入C.show,所以第一个输出b第二个输出undefined
最后我们来看一种奇怪的调用方式
function A(a){
alert(this+","+a+","+'A');
}
function B(b){
alert(this+","+b+","+'B');
}
var C = A.call;
A('a');
C.call(B,'a');
大家看到这估计已经懵逼了吧,想不到还可以这么调用吧
在这里第一个alert输出[object Window],a,A,结果正常,第二个alert输出a,undefined,A,这时就有人会问了,为什么a做了this指针而应该输出a的地方却输出了undefined
我们先来看一下调用一次call方法输出什么
function A(a){
alert(this+","+a+","+'A');
}
function B(b){
alert(this+","+b+","+'B');
}
var C = A;
A('a');
C.call(B,'a');
也就是说调用一次call方法是没问题的而且将他的this指向了B
那么在调用两次call方法时A的this指针域指向了arguments的第一个参数,而后面的参数则是作为了arguments的参数。
bind()
bind():这个方法会创建一个函数的实例,传入参数与call方法相同
var name = 'global';
function person () {
this.name = 'hero';
}
function print(age, job) {
console.log(this.name, age, job);
}
var Person = new person();
var printf = print.bind(Person);
printf(18, '前端工程师');
在这里将print通过bind方法将this的指针改为了print,返回了一个函数,调用函数并传入参数
输出hero 20 前端工程师
但是对bind方法new会让bind方法绑定的第一个参数消失
function Person(name, age) {
this.name = name;
this.age = age;
}
var _Person = Person.bind(null, 'hanzichi');
var p = new _Person(30);
因为new方法导致bind第一个参数无效