在ES6之前,我们要看一个函数内部的this到底是指向谁,那么就要通过观察函数是如何调用的,下面是函数的四种调用方式:
- 函数调用
示例1:
var age=18;
var p={
age:15
say:function(){
console.log(this.age);//window.age:18
}
}
var s1=p.say
s1(); //函数调用
由示例1可以知道函数调用方式的时候this是指向window。
- 方法调用
示例2:
var age=18;
var p={
age:15
say:function(){
console.log(this.age);//this:p
//this.age->p.age:15
}
}
p.say()//方法调用
示例2就是方法调用的实例,也就是对象调用了他自身的方法。最后,可以知道say函数里面的this指向是p对象。
- 构造函数的调用
示例3:
var age=18;
var p={
age:15
say:function(){
//this:say构造函数的实例,实例中并没有age属性,值为:undefined
console.log(this.age);
}
}
new p.say()//构造函数调用
//相当于:
var s1=p.say;
new s1();
示例3剖析:首先知道p是一个对象,他里面有say方法,那么此时有一个new关键字后面有一个函数调用,那么也就是说通过了new来调用一个函数,此时这个函数就可以说是构造函数咯!那么这个函数调用的方式就叫做构造函数调用咯!那么问题来了,此时函数内部的this是指向谁呢?示例3中的say函数内部的this是指向谁呢?输出打印结果可以知道this.age值为undefined,也就是并没有找到age的值。因为使用这个调用方式的函数内部的this就是该构造函数的实例。可是该构造函数的实例上并没有找到age属性,所以输出结果就是undefined。
- 上下文调用
实例4:
//上下文调用方式,有3种,call、apply、bind
function f1(){
console.log(this);
}
//call方法的第一个参数决定了函数内部的this的值
f1.call([1,3,5])
f1.call({age:20,height:1000})
f1.call(1)
f1.call("abc")
f1.call(true);
f1.call(null)
f1.call(undefined);
//上述代码可以用apply完全替换
实例4可以简单的这么理解:也就是call和apply方法里面的第一个参数决定了函数里面的this指向!
知道了call和apply方法调用,那么bind方法调用又是怎么样的?他们的区别是什么?
示例5:
//bind基本用法
function speed(){
console.log(this.seconds);
}
//执行了bind方法之后,产生了一个新函数,这个新函数里面的逻辑和原来还是一样的,唯一的不同是this指向{ seconds:100 }
var speedBind = speed.bind({ seconds:100 });
speedBind(); //100
(function eat(){
console.log(this.seconds);
}).bind({ seconds:360 })() //360
由示例5可以看出来,bind方法可以改变一个函数的this指向,这个和call以及apply是一样的,但是不同的区别是,通过增加bind()方法来调用一个函数时,此时会生成一个新的函数,这个新函数和原来的旧函数里面逻辑是一样的,只不过此时旧函数里面的this指向就会变成了指向bind方法括号中的参数对象了。