js —— 关于this指向的问题

this指向问题可以说是百分之百的面试内容。不管大公司小公司,都会问。最近在整理js的基础知识,特意将这个问题单独出来整理。通过查阅一些资料和阮一峰老师对这个问题的解析,自己也深受体会。下面就谈一谈我个人对this指向的理解。

一、this的定义

this指的是函数运行时所在的环境。
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁

二、关于不同调用方式,不同的结果

var obj = {
  foo: function () {},
};

var foo = obj.foo;

// 写法一
obj.foo();

// 写法二
foo();

上面代码中,虽然obj.foo和foo指向同一个函数,但是执行结果可能不一样。请看下面的例子。

var obj = {
  foo: function () {
    console.log(this.bar);
  },
  bar: 1,
};

var foo = obj.foo;
var bar = 2;

obj.foo(); // 1
foo(); // 2  等同于window.foo()
image.png

这种差异的原因是因为函数内部使用了this关键字。对obj.foo()来说,foo运行在obj环境,所以this指向obj;对于foo()来说,foo运行在全局环境,所以this指向全局环境window

例子1:

function a(){
    var user = "追梦子";
    console.log(this.user); //undefined
    console.log(this);  //Window
}
window.a();

例子2:

var o = {
    user:"追梦子",
    fn:function(){
        console.log(this.user);  //追梦子
    }
}
o.fn();

这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o。
例子3:

var o = {
    user:"追梦子",
    fn:function(){
        console.log(this.user); //追梦子
    }
}
window.o.fn();

window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象。
例子4:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //12
        }
    }
}
o.b.fn();
  • 情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。
  • 情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
  • 情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子4可以证明,如果不相信,那么接下来我们继续看几个例子。

例子5:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

三、构造函数this

function Person3() {
    this.name = 'king'; //这个this指向什么?
}
var person3 = new Person3();

this指向这个实例
要创建构造函数新的实例,就必须用new操作符,以这种方式调用构造函数会经历以下4个步骤:
1.创建一个新的对象;
2.将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
3.执行构造函数中的代码;
4.返回新对象。

//构造函数
function Person(name,sex) {  
    this.name = name;  
    this.sex = sex;  
} 

var per=new Person('king','male');

var obj  = {};
obj.__proto__ = Person.prototype;
Person.call(obj,'king','male');
image.png

四、当this遇到return

function fn()  
{  
    this.user = '追梦子';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined
function fn()  
{  
    this.user = '追梦子';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined
function fn()  
{  
    this.user = '追梦子';  
    return 1;
}
var a = new fn;  
console.log(a.user); //追梦子
function fn()  
{  
    this.user = '追梦子';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //追梦子

从以上四个代码块可以看出:
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

参考:
彻底理解js中this的指向,不必硬背。 - 追梦子 - 博客园
原型与原型链详解

你可能感兴趣的:(js —— 关于this指向的问题)