在js中,有一个很奇怪的关键字,就是this。this一般指向的是调用它的对象,它是基于函数的执行环境动态绑定的,有如下的几种情况:
1.全局环境
在非严格环境下,this一般指的是window对象,严格环境下,this指的是undefined。
2.作为对象的方法
这种情况下,this指向的是调用该方法的对象。
eg
var obj = {
name:'xw',
sayName:function(){
return this.name;
},
}; obj.sayName();//xw
但如果按如下方式来调用:
var sayName = obj.sayName(); sayName() // ''
这是因为函数执行的时候是在全局环境下,sayName变量保存着函数的指针,this自然而然的就指向window对象。避免这种情况,可以将this赋值给一个变量。eg
var obj = {
name:'xw',
sayName:function(){
var _this = this;
return _this.name;},
};
如果包含this的对象中有多个对象属性,尽管函数是被最外层对象调用的,this也只是指向它的上一级对象
eg
var obj = {
name:'xw',
sayName:function(){
var _this = this;
return _this.name;},
};
var obj = {
name:'xw',
school:{
name:"school",
sayName:function(){
return this.name;
}
},
sayName:function(){
return this.name
}
};obj.sayName()//xw; obj.school.sayName()//school
3.构造函数内部使用
构造函数内部使用的this代表的是有构造函数创建的实例
function Person(name){
this.name = name;
this.sayName = function(){
return this.name;
}
} var xw = new Person('xw');xw.sayName() //xw
另外,特殊情况,当return 出现在构造函数中,如果return的不是一个对象(null除外)的话,那么this的指向不变。但是如果return的是一个对象的话,那么this指向的是这个新对象,而不是new操作符创建的那个原本的对象。
4.箭头函数的this
一般情况下,this是根据函数的执行环境来动态决定的。es6中的箭头函数的this处理比较特别。es6中的箭头函数默认是没有this的,因此它的this是继承自父执行上下文的.由于箭头函数没有自己的this,因此箭头函数不可以用来做构造函数来使用。
eg
var name ='22';
var obj = {
name:'xw',
sayName:() => {
return this.name;},
}; obj.sayName()//'22',因为此时该箭头函数继承的是全局执行环境的this,即window对象,而普通函数的this指向的是obj这个对象
在比如
var name ='22';
var obj = {
name:'xw',
sayName:() => {
return () => {
return this.name;
}
},
}; obj.sayName()(); // 22,因为箭头函数没有this只能往上寻找,上面还是一个箭头函数,没有this,那么最后到了window全局执行环境下,this.name为22;如果修改下
var name ='22';
var obj = {
name:'xw',
sayName:function(){
return () => {
return this.name;
}
}, obj.sayName()(); // xw ,因为此时在上一级执行环境中找到了this,即指的是xw.
var name='22';
var obj = {
name:'xw',
grade:{
name:'zz',
sayName:function(){
return () => {
return this.name
}
}}
}
5.dom事件绑定的this
dom事件绑定的this代表的是对应的dom元素
6.call ,apply以及bind的使用方法
在js中可以动态的绑定this的指向,call和apply方法可以多次绑定this的指向,而且在绑定过程中会执行对应的函数,但是两者传参方式不同,call是一个个参数方式传参,apply是以数组形式传参。
eg
var xw= {
name: 'xw',
sayName: function(age){
return this.name + age;
}
}; var xx= {
name:'aa',
}; xw.sayName.call(xx,15);xw.sayName.apply(xx,[15]);
bind方法不同之处在于只能一次性绑定,返回的函数再绑定this指向就不会生效了,只会指向第一个绑定的this指向。
eg
var xw= {
name: 'xw',
sayName: function(age){
return this.name + age;
}
}; var xx = {name:'aa'};var xz = {name:'bb'}; let bb = xw.sayName.bind(xx,13); //aa13
let cc = bb.bind(xz,13); //aa13,注意,bind绑定方式传参数和apply方法相同