JavaScript 的 this 总是指向一个对象,而具体指向哪个对象是在 运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。而在 es6 中 箭头函数 中得到来改善,在定义的时候确定,多数情况是一个比较灵活,还是需要依据执行的环境推理判断
从四个大的方向去推理this指向的具体对象
- 作为对象的方法调用
- 作为普通函数调用
- 作为构造函数调用
- 函数的 call 或 apply 方法调用
1. 作为对象的方法调用
当函数作为对象的方法被调用时,this 指向该对象
let obj={
a:'a',
getName:function(){
console.log(this); // obj
console.log(this.a); // a
}
}
obj.getName() // 函数作为对象的方法,并且被当前对象调用
2. 作为普通函数调用
此时的 this 总是指 向全局对象,window
2.1 情况一 全局变量全局函数
let name = 'globName';
let getName=function(){
return this.name;
}
console.log(getName()); // globName
2.2 情况二 对象方法变为普通函数
let name = 'globName';
let obj={
name:'obj',
getName:function(){
return this.name;
}
}
// 普通函数
let getName2=obj.getName;
console.log(getName2()); // 输出:globName 而不是:期待的obj
同样this是window对象全局
2.3 情况三 局部函数
比如在一个对象函数内部,有一个局部的 callback 方法, callback 被作为普通函数调用时,callback 内部的 this 指向了 window,但我们往往是想让它指向 该obj对象本身,
window.name = 'globName';
let obj={
name:'obj',
getName:function(){
console.log(this.name); // obj
let callback =function(){
console.log(this.name); //globName
}
callback(); // 变成普通函数被调用
}
}
obj.getName();
2.3.1 解决方法一
定一个变量保存this的引用,通过上面的代码修改一下
... 省略
getName:function(){
console.log(this.name); // obj
let _this=this; // obj 对象的引用
let callback =function(){
console.log(_this.name); // 输出:obj
}
callback(); // 变成普通函数被调用
}
... 省略
2.3.1 解决方法二
箭头函数,箭头函数的this 在定义的时候确定
getName:function(){
console.log(this.name); // obj
// 局部函数改造为箭头函数
let callback =()=>{
console.log(this.name); // 输出:obj
}
callback(); // 变成普通函数被调用
}
3. 作为构造函数调用
当用 new 运算符调用函数时,该函数就是一个构造函数,总会返回一个对象,通常情况下,构造函数里的 this 就指向返回的这个对象,构造函数和普通函数是一模一样,唯一的区别是调用的时候
function myClass(){
this.name='LI';
}
let myName= new myClass(); // new 返回一个对象
console.log(myName.name); // LI 指向特定对象 而不是普通函数的window对象
有一种情况需要注意 当构造函数有返回值当时候,情况有所不同
3.1 构造函数 返回一个显式对象
如果返回一个显式的对象,那么this是该返回对象而不是之前期待的this;
function myClass2 (){
this.name='LI';
return{ // 显式的返回一个对象
name:'zhang'
}
}
let myName2= new myClass2();
console.log(myName2.name); // zhang
返回的是‘zhang’ 而不是期待的‘ LI’
如果构造器不显式地返回任何数据,或者是返回一个非对象类型的数据,就不会造成上述 问题;
3.2 构造函数 返回一个非对象类型
function myClass3 (){
this.name='LI';
return 'zhangs';
}
let myName3= new myClass3();
console.log(myName3.name); // LI
返回一个非对象类型 就是正常的this指向 new 的对象
4. 函数的 call 或 apply 方法调用
call 和 apply 都是函数的方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象,即动态的改变this
let obj1={
name:'li',
getName:function(){
return this.name;
}
}
let obj2={
name:'zh'
}
console.log(obj1.getName()); // li
console.log(obj1.getName.apply(obj2)); // zh
obj1.getName.apply(obj2) 改变来obj1 的原来this 指向,变为来obj2,
详细的apply 方法使用介绍可以参考
《javascript 之 apply()、call() 探索》
消失this
看下面的代码
let obj={
name:'objName',
getName:function(){
return this.name;
}
}
// 对象的方法
console.log(obj.getName()); // objName
let getName2=obj.getName;
// 普通函数的的方法
console.log(getName2()); // 返回空 什么都没有
getName2 普通函数调用,this 访问都是window对象。这个时候没有找到window对象的 name属性,理论上应该是undefined 实际在最新Chrome中为空,而 firfox 为
260

被折叠的 条评论
为什么被折叠?



