从对象中提取方法,为什么会丢失原对象,this变成指向window?

var label = 2
var obj={
    label:1
    a:function(){
        console.log(this.label);
    }
}
obj.a(); //1
var b = obj.a
b(); //2

为什么b会丢失原对象this,后面的原理是什么?

================补充:嵌套函数的this指向window怎么理解?=========================

如果说函数的this,由它运行时的执行环境来决定,比如这里的obj.a(),function的执行环境是obj所以this指向obj,而b()的执行环境是window,所以this指向window;

那么嵌套函数的this指向window,这个除了说“这是JS的语法规范规定的”,怎么从JS的实现原理上理解?

var label = "windowC"
function showThis(){
    var label = "innerC"
    function innerFun(){
        console.log(this.label)
    }
    innerFun()
}
showThis(); //windowC
阅读 4.7k
8 个回答

obj.a的值,不过是存放了它代表方法的地址,当var b = obj.a时,b变量存放的也是该方法的地址;
而另一方面,全局声明的变量,是window的属性,故window.b == b是成立的;
调用b()时,就相当于window.b()一样。再跟obj.a()对比,明白了吧;
当然,就指向了window这个全局对象。给个赞也行哇

var b=obj.a;就等价于var b=function(){console.log(this.label)};这里相当于是声明了一个函数,this指向window

你声明的b,其实就相当于window.b,所以打印2没有错啊。理解this很重要
obj.a执行过程中a中的this指向的是obj,
而b(),相当于window.b(),this指向的是window

最近在翻高程3的书,应该可以帮到楼主。

首先,需要明确作用域的概念。

obj.1()//1,这块,a中的functon中的this的作用域被限定在了obj这个对象当中,所以this的label的值则为你在obj对象中定义的属性label的值,这个值为1。

接下来一行,你var了一个变量b,注意,很重要的一点,你的这个变量b是在全局作用域(window)中定义的,然后,你讲obj.a方法赋值给b。接下来,(敲黑板,重点来了),你在全局作用域环境下(window)执行了b,而this的指向是需要根据执行环境来确定的,所以在全局作用域环境下label的值变为了你第一行写的2。

如果还有不懂得继续讨论哈,这个是基于我个人的理解

看了各位的答案,加上自己得到的理解,自问自答一下:

我是在结合obj在内存的存储状况来理解的,一开始也是在这里遇到了困惑:

var obj={
    label:1
    a:function(){
        console.log(this.label);
    }
}

obj中,label和1都存储在obj中,a作为一个变量存在obj中,a对应的function的实体存储在obj之外,obj只是存储一个指针。因此obj.a()的this指向a并不是因为实体function存在里面,而是孤立的实体function在被调用时,处于obj这个执行环境中;同理,b()的this指向window,也是因为孤立的实体function在被调用时,处于window这个执行环境中

clipboard.png

this是根据函数执行环境变化的 如果你后面想拿到当前的this可以先把this保存在一个变量中或者使用apply/call/bind来绑定this

    a:function(){
        let that = this;
        console.log(that.label);
    }
    //或者在调用的时候使用bind
    let b = obj.a
    b.bind(a)() //1

只看结论的话就是,函数内部的this指向,由其调用方式决定:函数被对象所拥有则this指向该对象;函数独立调用,则this指向undefined,非严格模式指向全局对象。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题