this是JS中的关键字,this的指向中函数定义时确定不了,只有 函数指向的时候才能确定this到底指向谁,this的最终指向的是那个调用他的对象
牢记以下三点
- this指向的,只可能是对象!
2.this指向谁,不取决于this写在哪!而是取决于函数在哪里进行调用。
3.this指向的对象,称之为函数的上下文context,也叫函数的调用者。
下面我用几个例子解释一下this
例子1:
function fn(){
var aa= "88";
console.log(this.aa); //undefined
console.log(this); //Window
}
fn();
我们上面说this只有在函数执行的时候,才能去判断它最终指向的调用它的对象,函数是由window对象调用的,所以自然指向window,然而在window的属性中,没有aa这个变量,所以结果为undefined
function fn(){
var aa= "88";
console.log(this.aa); //undefined
console.log(this); //Window
}
window.fn();//window可以省略 等同于上面的代码
例子2:
var obj = {
name:"张三",
who:function(){
console.log(this.name); //张三
}
}
obj.who();
函数在对象obj里面,调用函数时,是通过obj.who()调用的,所以这里的this指向obj,而obj里面是有一个name属性值的,所以结果为张三。
结合这两个例子,我们应该了解了this指向调用它的对象,但是对this的了解还不够深入,下面我再写几个例子补充一下
例子3:
var name ="李二" ;
var person = {
name:"李三",
say:function(){
console.log(this.name); //李三
}
}
window.person.say();
从这个例子可以看出,如果按照上面的推论的话,这里的this最终应该指向window,结果为李二才对。接着看下面这个例子
var obj= {
a:10,
b:{ a:12,
fn:function(){
console.log(this.a);//12
}
}
}
obj.b.fn();
如果根据上面的推断的话,这里的this应该指向obj才对,this.a结果应该为10才对。这样看来,可能你会觉得开头对于this指向的认知是错误的。其实并不是,只是不够准确而已。以下三条补充
如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window。
如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
如果一个函数中有this,这个函数中被多个对象包含,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
下面再看几个例子
例子4:
var obj = {
a: 1,
b: {
fn: function() {
console.log(this.a) // undefined
}
}
}
obj.b.fn()
输入的值是undefined,也就是说,这个时候this指向的是b的作用域,而b中没有定义a,所以是undefined
var obj = {
a: 1,
b: {
a: 2,
fn: function() {
console.log(this) // Window
console.log(this.a) // undefined
}
}
}
var x = obj.b.fn
x()
谁调用,指向谁,这一句var x = obj.b.fn只是进行了赋值,把 fn赋值给了全局变量 x ,然而最终的调用时机是在 window作用域调用的函数 x(), 所以 this的指向是window对象
那我们如何改变 this 的指向呢?
通过 call, apply, bind 改变 this 的指向
例子5:
var name = "小猫";
var food = "鱼"
var obj = {
name:this.name,
food:this.food,
state: function(name, food){
console.log(`${this.name} 最喜欢的食物是${this.food}`)
}
}
var skills = {
name: '狗',
food: "骨头",
}
obj.state() //小猫 最喜欢的食物是鱼
obj.state.call(skills)//狗 最喜欢的食物是骨头
obj.state.apply(skills) //狗 最喜欢的食物是骨头
obj.state.bind(skills)()//狗 最喜欢的食物是骨头
从上面看出来, call, apply, bind把this的指向改变为call, apply, bind所传入的第一个参数, 除此之外,他们是没有什么区别的,看看下面的例子
var name= "兔子"
var food = "胡萝卜"
var obj = {
food:this.food,
name:this.name,
state: function(name, ow){
console.log(`${this.name} 爱吃 ${this.food},但是${name}爱吃${ow}`)
}
}
var skills = {
name: "熊二" ,
food: '蜂蜜'
}
obj.state("羊","草") //兔子 爱吃 胡萝卜,但是羊爱吃草
obj.state.call(skills,"大灰狼","小绵羊") //熊二 爱吃 蜂蜜,但是大灰狼爱吃小绵羊
obj.state.apply(skills,["狐狸","葡萄"]) // 熊二 爱吃 蜂蜜,但是狐狸爱吃葡萄
obj.state.bind(skills,"猫","鱼")() //熊二 爱吃 蜂蜜,但是猫爱吃鱼
apply第二个参数接受的是一个数组, call 直接按参数排列就可以了,而 bind 跟call相似,只不过后面多了个 ()
上面是本人对于this指向的一些理解,如有错误或不足,望指出。