来一起康康这道题呀
涉及到:原型链、 对象、 变量提升、 函数提升、 运算符优先级
<script>
function fn() {
getValue = function () { console.log(1); }
return this;
}
fn.getValue = function () { console.log(2); };
fn.prototype.getValue = function () { console.log(3); };
var getValue = function () { console.log(4); };
function getValue() { console.log(5); }
getValue();
fn().getValue();
getValue();
new fn.getValue();
new fn().getValue();
new new fn().getValue();
</script>
结果:

答案:
411233
考察知识点:
考察面试者的JavaScript的综合能力,变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级等知识
解析:
第一问getValue();
引擎在读取js代码的过程中,分为两步。第一个步骤是整个js代码的解析读取,第二个步骤是执行。
在JS代码执行之前,浏览器的解析器在遇到 var 变量名 和function 整个函数提升到当前作用域的最前面。
记住三个知识点:
1.变量提升只会提升变量名的声明,而不会提升变量的赋值初始化。
2.函数提升优先于变量提升,即函数提升在变量提升之上。
3.函数声明会将函数提升(包括声明function和赋值=),函数表达式只会将变量var提升。
所以题目中的
var getValue = function () { console.log(4); };
function getValue() { console.log(5); }
最终结果相当于
var getValue;
function getValue() { console.log(5); }
getValue = function () { console.log(4); };
所以第一问的答案就是4,5的函数声明被4的函数表达式覆盖了
第二问fn().getValue();
-
fn().getValue()
,先执行了fn函数,然后调用fn函数的返回值对象的getValue属性函数;
2.注意,fn函数中的第一句,getValue =function () { console.log(1); };
没有用var进行声明,执行到这时,实际上,将外层作用域的getValue函数修改了;
3.之后,fn函数返回this,thi s的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定thi s到底指向谁,而此处的直接调用方式,this指向window对象,所以此处相当于执行window.getValue()
,现在getValue已经被修改成console. log(1),所以输出1
第三问getValue();
第二问中,执行完fn函数,getValue函数 已经被修改了,现在已经是console. log(1),所以这输出1
以下分析用到的知识点:
- 圆括号 优先级是20
- new fn()是new有参数列表 优先级是19;
- . 成员访问 优先级是19
- 函数调用 优先级 19
-
new fn是new无参数列表 优先级是18;
MDN原图:
image.png
当一个函数用作构造函数时(使用new关键字),它的
this
被绑定到正在构造的新对象。
第四问new fn. getValue();
1.点比new无参列表的优先级高,所以相当于new (fn. getValue())
- 当点运算完后又因为有个括号(),此时就是变成new有参数列表,函数调用和new有参数列表的优先级都是19,从左到右执行;
- 最终相当于将getValue函数
function() { console. log(2);};
作为构造函数来执行,所以输出2。
第五问new fn().getValue() ;
先执行实例化new fn(),所以 调用该实例对象的方法getValue指的是构造函数原型上的getValue方法,打印值为3。
第六问new new fn().getValue() ;
new new fn().getValue() ;
等价于 new (new fn().getValue)() ;
有问题仔细研读上边提到的相关那几个知识点就能搞懂了(^-^)V
大功告成,我怎么这么棒🤣
网友评论