请教一个关于 this 的问题

2019-01-30 18:34:13 +08:00
 fourstring

代码如下:

var name="Window";
var object={
    name:"object",
    getName:function (){
        var a= function(){
            return this.name;
        };
    	console.log(a());
    	return a;
    }
}
object.getName()();

运行结果:

Window
Window

我的问题在于console.log(a());这一行。return a后,是在全局作用域中执行的返回的匿名函数,所以this的值是window。但是我在getName函数中直接执行a()的话,根据this的定义“ this 指向函数运行时的执行环境对象”,而每个函数执行时都会创建一个自己的执行环境,那么a()执行时this的值应该是getName函数的环境对象,这样 a 函数内对this.name的引用就应该得到undefined。请问我的理解有什么问题呢?谢谢:)

4660 次点击
所在节点    JavaScript
40 条回复
4ark
2019-01-30 18:50:23 +08:00
https://www.v2ex.com/t/529532 看看吧,另外贴代码的时候能不能带有格式啊,看着真糟心!
4ark
2019-01-30 18:54:27 +08:00
就你这段代码而言,a 并不属于任何对象,也没有通过 call 等方法调用,所有这样的函数 this 默认指向 Window,如果是严格默认下,就是 undefinde。
4ark
2019-01-30 18:56:13 +08:00
收回我说的第一句话,才发现我的文章代码也没有格式,为什么 V2EX 会这样??
Trim21
2019-01-30 19:08:06 +08:00
@4ark 其实我这边手机看着两个帖子里的代码都有格式…
4ark
2019-01-30 19:09:32 +08:00
@Trim21 因为我用的是 v2er 的客户端,才发现这个问题,现在已卸载。
4ark
2019-01-30 19:12:19 +08:00
@Trim21 想问一下您手机端用的啥客户端?
Trim21
2019-01-30 19:13:33 +08:00
@4ark chrome
4ark
2019-01-30 19:14:31 +08:00
@Trim21 使用起来体验没有客户端好,虽然不会有显示问题
Nitroethane
2019-01-30 19:15:59 +08:00
@4ark 最新的 beta 版已经实现了代码格式化功能:
https://imgur.com/a/0uF0P3M
4ark
2019-01-30 19:20:31 +08:00
@Nitroethane 求下载链接,感激不尽!
4ark
2019-01-30 19:28:01 +08:00
@Nitroethane 已在 play 商店搜到
rabbbit
2019-01-30 19:41:38 +08:00
this 是什么取决于如何调用
本文中 a 函数的调用者是 a() 而非外层的 object.getName()

当 a 函数被作为变量调用时, 会将内部方法 GetBase(ref). ImplicitThisValue 返回的值作为 thisArg(通常是 undefined)
http://ecma-international.org/ecma-262/5.1/#sec-11.2.3

在进入函数时
1 如果是严格模式,把 this 指向 thisArg
2 如果 thisArg 为 undefined,则将 this 指向 window
http://ecma-international.org/ecma-262/5.1/#sec-10.4.3

总之一句话,作为变量调用的函数里边的 this 都指向 window
OSF2E
2019-01-30 19:54:13 +08:00
《 Javascript 高级程序设计(第三版)》( P73 ) 4.2 执行环境与作用域
rabbbit
2019-01-30 19:55:32 +08:00
另外补充下
ImplicitThisValue 通常返回 undefined, with 除外
fourstring
2019-01-30 19:59:42 +08:00
@OSF2E #13 谢谢,我看的就是这本书。我之所以会认为 a()的结果是"object",就是因为这本书 5.5.4 里说 this “引用的是函数执行的环境对象”,然后 4.2 节说“每个函数都有自己的执行环境”,我看了下面别的 v 友回复以后,觉得应该是我对“执行环境”理解有误,但是这本书里确实没有明确讲解函数的执行环境究竟是什么(也就是不是词法环境)。
fleam
2019-01-30 20:01:49 +08:00
我总结的就是相关性就近原则,菜鸟飞过。。。
X37B
2019-01-30 20:38:06 +08:00
this(4 个规则):函数位置上的调用形式
默认绑定
独立调用 fn()
this -->window "use strict" this --> undefined

隐式绑定
对象.对象.fn()
this -->最近的调用者
隐式丢失?
使用隐式调用的形式进行传参 赋值;使用其他形式进行调用 this 的指向发生改变
解决隐式丢失?
硬绑定 bind 返回一个新的函数

显示绑定
apply
call
立即调用
this --> 绑定的对象

构造绑定
new fn()
this --> 构造出来的实例对象

当一行代码出现多个绑定,this 绑定优先级:new --> 显示 --> 隐式 --> 默认
shintendo
2019-01-30 20:42:26 +08:00
其实很简单,你的 this 在哪个函数里面?在 a 里面,那么 this 的值只取决于 a 被谁调用,跟其它什么 getName 没有任何关系。
而所谓的 a 被谁调用,指的是“调用者.a()”这种调用,不是说 a()写在 getName 里面就是被 getName 调用了这种意思。
fourstring
2019-01-30 20:58:04 +08:00
@X37B #17 请问知道这样的知识什么地方或者书能看到呢
secondwtq
2019-01-30 21:17:41 +08:00
@fourstring 犀牛书应该是这样理解语言设计者的意图的:词法作用域和 this 都属于函数运行环境 /上下文,现在的实践中,一般词法作用域是写代码时固定的,this 允许用户在运行时动态指定上下文,并且这东西和函数调用语法关联,因此也是一种“环境”

实际上现在的 OO 语言对于 this 的实现基本就是函数参数,也就是非要说的话所有参数都是“环境”的一部分 ... 不过 OO 的语义上 this 确实有环境的意思

词法作用域环境也可以动态绑定,用 eval 或者 with 就行,只不过现在没人用了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/531950

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX