[前端基础]一道前端小题的简单分析

有这样一道前端小题, 问输出什么:

function Foo() {
    getName = function () { console.log(1); };
    return this;
}
Foo.getName = function () { console.log (2);};
Foo.prototype.getName = function () {console.log(3);};
var getName = function () { console.log (4);};
function getName() { console.log(5);}
 
//请写出以下输出结果:
Foo.getName();  // Q1
getName();// Q2
Foo().getName(); // Q3
getName();// Q4
new Foo.getName();// Q5
new Foo().getName();// Q6
new new Foo().getName();// Q7

回答:
1、 Q1
答案:2。 Foo.getName 为调用Foo的静态方法

2、 Q2
答案:4。function getName() {} 的写法为函数声明式写法。 var getName = function() {} 为函数表达式写法

JavaScript 解释器中存在一种变量声明被提升的机制,也就是说函数声明会被提升到作用域的最前面,即使写代码的时候是写在最后面,也还是会被提升至最前面。而用函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用。 即函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用。而函数表达式的值是在JS运行时确定,并且在表达式赋值完成后,该函数才能调用。

所以function getName() {} 会提升至顶部, 运行时 被var getName = function() {} 覆盖

3、 Q3
答案: 1。Foo() 执行, getName 为全局变量; Foo()返回this , this 指向window , Foo() .getName 为 window.getName

4、 Q4
答案: 1。 直接调用getName函数,相当于window.getName(),getName 已经被第3步修改

5、Q5

答案: 2 。 此处涉及符号优先级问题。
image.png

对于new Foo.getName() , new Foo 为 「new 无参数列表」 优先级在表格中为18,Foo.getName 为成员访问,优先级为19 ;所以 new Foo.getName() 的执行为 new (Foo.getName)()

6、 Q6
答案:3 。 new Foo().getName() 按优先级判断为 (new Foo()).getName()
new Foo() 为Foo的实例,返回的是this,而this在构造函数中本来就代表当前实例化对象,最终Foo函数返回实例化对象。 即实例化对象的getName 方法,实例方法中没有,去原型上查找,故为3

7、 Q7
答案:3。 Q7 是Q5 与Q6问题的组合, 相当于

 new ((new Foo()).getName)();

其他小知识:

1、JS中构造函数可以有返回值也可以没有。

  • 如果没有返回值,则返回实例化对象。
  • 若有返回值则检查其返回值是否为引用类型。如果是非引用类型,如基本类型(String,Number,Boolean,Null,Undefined)则与无返回值相同,实际返回其实例化对象。
  • 若返回值是引用类型,则实际返回值为这个引用类型。

hi 今天的你点赞了没~~

你可能感兴趣的:([前端基础]一道前端小题的简单分析)