FE-Interview icon indicating copy to clipboard operation
FE-Interview copied to clipboard

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

Open Genzhen opened this issue 4 years ago • 8 comments

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

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

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

Genzhen avatar Jun 22 '20 12:06 Genzhen

答案 undefined

Genzhen avatar Jun 22 '20 12:06 Genzhen

这里并不是因为赋值给 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 avatar Jan 15 '21 05:01 userkang

解释下这两个步骤: 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。

userkang avatar Jan 15 '21 05:01 userkang

这里并不是因为赋值给 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♪(・ω・)ノ

Genzhen avatar Jan 15 '21 07:01 Genzhen

解释下这两个步骤: 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 avatar Apr 28 '21 09:04 mrluos

解释下这两个步骤: 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 不知道我这样理解对不对?

mrluos avatar Apr 28 '21 10:04 mrluos

解释下这两个步骤: 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 avatar Sep 14 '21 03:09 Chorer

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

SnailOwO avatar Nov 17 '21 08:11 SnailOwO