js的this指向问题

clipboard.png

结果指向window,为啥啊,这不是个闭包吗?

阅读 7.1k
13 个回答

javascript中的this指向与调用者有关,分为以下4种情况

  • 函数调用,即直接调用a(),这种this指向global对象,在浏览器即window,例如:
function a() {
    console.log(this)
}
a() //window
  • 方法调用,即作为对象的方法调用,此时指向对象本身,例如
var a = {
    b : function(){
        console.log(this)
    }
}
a.b() // a
  • 用new调用,此时返回new出的实例,例如
function A(){
    console.log(this)
}
var a = new A() // a
  • 用call,apply,bind调用,绑定到传入的参数对象,如
var a= function(){
    console.log(this)
}
var b = []
a.call(b) // []

其实你这个问题,等于是在问,js中 new 的操作原理到底是啥?,或者说new 调用和函数普通调用有啥区别http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html 看完这篇文章你就理解啦。

补充,针对你的问题,先抛出结论:

  • 构造函数在不返回值的情况下,默认返回新对象实例
  • 如果函数返回值为常规意义上的数值类型(Number、String、Boolean)时,new函数将会返回一个该函数的实例对象,而如果函数返回一个引用类型(Object、Array、Function)时,则new函数与直接调用函数产生的结果相同。

根据《高程》这本书上的说明:构造函数本身也是函数,只不过可以用来创建对象而已,其与普通函数的唯一区别,就在于调用方式的不同。任何函数如果通过 new 操作符来调用,那么就可以作为构造函数,反之就是普通函数调用。

构造方式调用实际上会经历以下 4 个步骤:

  • (1)创建一个对象;
  • (2)设置原型链,或者叫绑定构造函数原型
  • (3)将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象),执行函数体
  • (4)判断返回值类型,并返回。如果是值类型,就丢弃它,还是返回 instance。
    如果是引用类型,就返回这个引用类型的对象,替换掉 instance。

注意:
1、若无返回值,即相当于返回 return undefined,undefined 是值类型的,因此丢弃它,返回 instance。正好对应上面结论第一条。

2、 如果return this相当于返回一个引用类型的对象,它自己就是instance,无所谓替换不替换了。

演示代码什么呢的,书上就有,或者自行模拟下。

下面回到问题:

F 返回的是引用类型的 C 函数,那么就替换掉以F new 调用出来的实例,那么自然就是普通的 C 函数调用 (而且是在全局环境中),自然 this 指向 window。

new 的出现,我个人认为是 JS 语言在演进中为了向传统 OO 语言看齐,模拟 class,完成工厂模式,或者说是一种 “糖”,减轻重复劳动。 当然,我也是 YY 的。以上内容也是网上和书上总结搬运的,如若错误请指正,谢谢!

如果改成这样,答案就不是window了。
`function F(){

    function C(){
        return this;
    }
    return new C(); // 加了一个new
}`

解释一波 var o = new F()的时候,关键字new内部做了很多事情(比如把this指向当前new出来的o实例),但是F()return 了一个C(),这个时候,前面new F()new做的事情,等于白干,return这里,改变了所有结果。

然后,就是`C()`内部干了什么,结果就是什么,这里就是直接调用了`C()`一样。结果就是`window`。

this绑定规则有4点,按优先级1到4判断

  1. 由new调用?绑定到新创建的空对象;
  2. 由call、apply、bind调用?绑定到指定的参数对象;如foo.call(obj)
  3. 由上下文对象调用?绑定到这个上下文对象;如obj.foo()
  4. 默认情况下绑定到全局对象,foo();在严格模式下绑定到undefined;

上面代码中 符合第4种情况,所以是 绑到了 window,当然也可能是 undefined

指向window。

因为C执行的方式为C()直接调用,所以返回的this已经是window,和外面的F没有关系。

new 的时候如果构造函数有返回值且返回值是一个对象,那么这里new命令就会返回这个对象。

函数体内的this在非严格模式下都是指向window。

那么也就是this指向window

函数中this指向全局

相当于直接执行了 C();所以指向window

看this的调用位置,显然是默认绑定的方式。指向全局对象

this在函数定义的时候是不确定的,只有在函数调用的时候才知道

  this的指向取决于函数的调用方式
   1:直接调用:相当于window在调用
      直接调用函数 这个函数就是你是一个普通的函数
   2:构造函数调用:     
        构造函数里面的this在没有new的情况下,它其实是一个隐式对象
           在new的时候 它指向this的实例对象
   3:对象调用:
      方法里面的this指向该对象
   4:事件处理函数所调用,this指向触发该事件前面的那个元素对象
   5:定时器调用的时候,this指向window
 特别注意: 函数前面如果什么都没有那么this指向window

你这段代码写再多,但只看一点,
return前面的这个 C();
这个方法的执行,肯定是window来调用的

new绑定的效果是将this绑定到new出来的实例对象上,但这仅代表F函数在这次调用时,其内部的this指向new出来的实例对象。再看看函数内部做了哪些事情:声明了一个具名函数c,返回this(没到调用的时候不用管这个this指向的是谁),然后return出执行c的结果,这时候看这个c函数,是四种绑定方式中的默认绑定(浏览器环境下绑定到window上),所以c函数在这次执行的时候,内部的this指向window。而c函数又返回this,那就是返回window了。也就是F函数的这次调用返回的就是window。给它赋值给o,那o打印出来当然是window了。

1 篇内容引用
推荐问题
宣传栏