Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day12:写出执行结果,并解释原因 #48

Open
Genzhen opened this issue Jun 22, 2020 · 8 comments
Open

Day12:写出执行结果,并解释原因 #48

Genzhen opened this issue Jun 22, 2020 · 8 comments

Comments

@Genzhen
Copy link
Collaborator

Genzhen commented Jun 22, 2020

var foo = {
        bar: function(){
            return this.baz;
        },
         baz:1
    }
console.log(typeof (f=foo.bar)());
//写出执行结果,并解释原因

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案
欢迎大家在下方发表自己的优质见解
二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。

@Genzhen Genzhen changed the title Day12:写出执行结果,并解释原因 Day12:写出执行结果,并解释原因 Jun 22, 2020
@Genzhen
Copy link
Collaborator Author

Genzhen commented Jun 22, 2020

答案
undefined

@Genzhen Genzhen closed this as completed Jul 21, 2020
@Genzhen Genzhen reopened this Jul 29, 2020
@userkang
Copy link

userkang commented Jan 15, 2021

这里并不是因为赋值给 f ,相当于f(),所以this指向window的。
不然试试下面代码也会打印 undefined

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

下面简单从规范的角度判断这个this指向,可以分以下几个步骤:

1.计算 MemberExpression 的结果赋值给 ref

2.判断 ref 是不是一个 Reference 类型

2.1 如果 ref 是 Reference,并且 IsPropertyReference(ref) 是 true, 那么 this 的值为 GetBase(ref)

2.2 如果 ref 是 Reference,并且 base value 值是 Environment Record, 那么this的值为 ImplicitThisValue(ref)

2.3 如果 ref 不是 Reference,那么 this 的值为 undefined

@userkang
Copy link

userkang commented Jan 15, 2021

解释下这两个步骤:
1、MemberExpression 我们可以简单理解为括号前的部分,针对这题就是 (f=foo.bar) 这部分。

2、Reference 是规范类型的一种。如果通过 GetValue 方法从 Reference 类型中获取值,则该 MemberExpression 返回结果不再是 Reference 类型。
这里的关键就是判断 MemberExpression 的返回结果是不是 Reference 类型。
由于 f=foo.bar 存在赋值操作符,根据规范 11.13.1 Simple Assignment ( = ) 规定,其第三步使用了 GetValue(ref),故返回值不是 Reference 类型。
对照上述 2.3 的规范,如果表达式返回值不是 Reference 类型,那么 this 的值为 undefined,在非严格模式下,被隐式转换为全局对象 window。

@Genzhen
Copy link
Collaborator Author

Genzhen commented Jan 15, 2021

这里并不是因为赋值给 f ,相当于f(),所以this指向window的。
不然试试下面代码也会打印 undefined

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

下面简单从规范的角度判断这个this指向,可以分以下几个步骤:

1.计算 MemberExpression 的结果赋值给 ref

2.判断 ref 是不是一个 Reference 类型

2.1 如果 ref 是 Reference,并且 IsPropertyReference(ref) 是 true, 那么 this 的值为 GetBase(ref)

2.2 如果 ref 是 Reference,并且 base value 值是 Environment Record, 那么this的值为 ImplicitThisValue(ref)

2.3 如果 ref 不是 Reference,那么 this 的值为 undefined

感谢提出指正Thanks♪(・ω・)ノ

@mrluos
Copy link

mrluos commented Apr 28, 2021

解释下这两个步骤:
1、MemberExpression 我们可以简单理解为括号前的部分,针对这题就是 (f=foo.bar) 这部分。

2、Reference 是规范类型的一种。如果通过 GetValue 方法从 Reference 类型中获取值,则该 MemberExpression 返回结果不再是 Reference 类型。
这里的关键就是判断 MemberExpression 的返回结果是不是 Reference 类型。
由于 f=foo.bar 存在赋值操作符,根据规范 11.13.1 Simple Assignment ( = ) 规定,其第三步使用了 GetValue(ref),故返回值不是 Reference 类型。
对照上述 2.3 的规范,如果表达式返回值不是 Reference 类型,那么 this 的值为 undefined,在非严格模式下,被隐式转换为全局对象 window。

从 《你不知道的JavaScript 上卷》中有这么一个例子
function foo() { console.log( this.a ); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); // 3 (p.foo = o.foo)(); // 2
`
书里是这样说的:赋值表达式 p.foo = o.foo 的返回值是目标函数的引用,因此调用位置是 foo() 而不是
p.foo() 或者 o.foo()。根据我们之前说过的,这里会应用默认绑定

@mrluos
Copy link

mrluos commented Apr 28, 2021

解释下这两个步骤:
1、MemberExpression 我们可以简单理解为括号前的部分,针对这题就是 (f=foo.bar) 这部分。
2、Reference 是规范类型的一种。如果通过 GetValue 方法从 Reference 类型中获取值,则该 MemberExpression 返回结果不再是 Reference 类型。
这里的关键就是判断 MemberExpression 的返回结果是不是 Reference 类型。
由于 f=foo.bar 存在赋值操作符,根据规范 11.13.1 Simple Assignment ( = ) 规定,其第三步使用了 GetValue(ref),故返回值不是 Reference 类型。
对照上述 2.3 的规范,如果表达式返回值不是 Reference 类型,那么 this 的值为 undefined,在非严格模式下,被隐式转换为全局对象 window。

从 《你不知道的JavaScript 上卷》中有这么一个例子
function foo() { console.log( this.a ); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); // 3 (p.foo = o.foo)(); // 2
`
书里是这样说的:赋值表达式 p.foo = o.foo 的返回值是目标函数的引用,因此调用位置是 foo() 而不是
p.foo() 或者 o.foo()。根据我们之前说过的,这里会应用默认绑定

个人想法:
这里的意思是返回的不是p.foo然后()调用,而是o.foo的引用然后直接()调用相当于是在全局下调用了,
var foo = { bar: function(){ return this.baz; }, baz:1 } var baz=3; console.log(typeof (foo.bar=foo.bar)()); 输出number
不知道我这样理解对不对?

@Chorer
Copy link

Chorer commented Sep 14, 2021

解释下这两个步骤:
1、MemberExpression 我们可以简单理解为括号前的部分,针对这题就是 (f=foo.bar) 这部分。
2、Reference 是规范类型的一种。如果通过 GetValue 方法从 Reference 类型中获取值,则该 MemberExpression 返回结果不再是 Reference 类型。
这里的关键就是判断 MemberExpression 的返回结果是不是 Reference 类型。
由于 f=foo.bar 存在赋值操作符,根据规范 11.13.1 Simple Assignment ( = ) 规定,其第三步使用了 GetValue(ref),故返回值不是 Reference 类型。
对照上述 2.3 的规范,如果表达式返回值不是 Reference 类型,那么 this 的值为 undefined,在非严格模式下,被隐式转换为全局对象 window。

从 《你不知道的JavaScript 上卷》中有这么一个例子
function foo() { console.log( this.a ); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); // 3 (p.foo = o.foo)(); // 2
`
书里是这样说的:赋值表达式 p.foo = o.foo 的返回值是目标函数的引用,因此调用位置是 foo() 而不是
p.foo() 或者 o.foo()。根据我们之前说过的,这里会应用默认绑定

个人想法:
这里的意思是返回的不是p.foo然后()调用,而是o.foo的引用然后直接()调用相当于是在全局下调用了,
var foo = { bar: function(){ return this.baz; }, baz:1 } var baz=3; console.log(typeof (foo.bar=foo.bar)()); 输出number
不知道我这样理解对不对?

我也觉得这样更容易理解。从规范的角度去理解可能也行,但这不就是间接说明如果没有阅读过规范,这道题就做不出来了吗?难不成每个人都要阅读规范。。?

@SnailOwO
Copy link

这是属于this隐式丢失三项中的,函数别名。
this隐式丢失有三种:函数别名、回调传参、将函数值传给语言内置函数(setTimeout第一个参数等等等)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants