this指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁
例子1:
function a(){ var user = 'nihao'; console.log(this.user); //undefind console.log(this); //window } a();
上面的this最终指向的是调用它的对象,它的调用对象其实是window对象
例子2:
var b = { user:'nihao', fn1:function(){ console.log(this.user); } } b.fn1();
这里的this指向的是对象b,因为调用这个fn1是通过b.fn1()执行的,那么也肯定会指向对象b,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁去调用它它就会指向谁 。
这句话有些问题,下面的例子将证明以上的观点不准确:
例子3:
在上个代码的基础上加上一个window为什么不会指向window?
var b = { user: 'nihao', fn1: function () { console.log(this.user); console.log(this); //{user: "nihao", fn1: ƒ} } } window.b.fn1(); //nihao
按照上面的例子,this的最终指向应该是调用它的对象
window是js中的全局对象,我们创建的变量只是给window添加属性,并不是真正调用window对象,其实这可以用window.b对象
例子4:
var c= { a:10, b:{ a:12, fn2:function(){ console.log(this.a); } } } c.b.fn2();
这里为什么会执行12而不是10?
1、如果函数中有this,但是没有被上一级对象所调用,那么指向的就是window(非严格版)
2、如果一个函数中有this,这个函数被上一级对象所调用,那么this指向的就是上一级对象(就近原则)
3、如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层对象所调用,那么this 它也是指向上一级对象(就近原则)
再看下面的例子
var c = { a: 10, b: { // a:12, fn: function () { console.log(this.a); //undefined } } } c.b.fn();
如果这里把b中的a给注掉,那么他还是指向它上一级(也就是b对象),不管它这个对象中有没有this所需要的东西。
还有一种比较特殊的情况:
例子5:
var c = { a: 10, b: { a: 12, fn: function () { console.log(this.a); //undefined console.log(this); //window } } } var d = c.b.fn; d();
这里为什么指向window?
this永远指向的是最后调用它的对象,虽然这个例子中fn是被对象b所引用,但是又把fn赋值给变量d的时候d就变成了最终指向(也就是window),例子3的话直接执行fn。
并不能说哪句话不正确,只不过在不同的情况下指向的对象会有一些不同,上述的总结每个地方都有一些小的错误。
构造函数版this:
function Fn() { this.user = "nihao"; } var a = new Fn(); console.log(a.user); //nihao
这里之所以对象a可以输出函数Fn中的user是因为:
new关键字可以改变this的指向
为什么this会指向a?首先new关键字会创建一个空对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样函数内部的this就会被这个空的对象所替代
将这个this指向对象a,因为new关键字创建了一个对象实例,这里的var a仅仅创建了一个Fn的实例(相当于复制一份Fn给a),只是创建,并没有执行。调用这个函数Fn的是对象a,所以this指向就是a,为什么a中会有user,因为已经复制了一份Fn函数到a中,用了new关键字就是等同于复制了一份。
当this中出现return时:
function fn(){ this.user = 'nihao'; return {}; //return function(){}; } var a = new fn(); console.log(a.user); //undefined
当给return中添加任何对象时:
function fn(){ this.user = 'nihao'; return; // return1; // return undefined; // return false; // return null; } var a = new fn(); console.log(a.user); // nihao
如果返回值是一个对象,那么this就指向那个对象,如果不是对象那还是this指向函数的实例
还要注意一点,(function(){})()立即执行函数返回的是window全局