阅读 84

一道很经典的运算符优先级面试题, 一起做做?

简介

最近我看到一道关于运算符优先级的面试题, 非常的经典. 在这里和大家分享一下。

面试题

function Foo(){
  console.log('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);
}

// 请问,下面分别打印的值是什么?
// 1. 
Foo.getName(); 

// 2.
getName();

// 3.
Foo().getName();

// 4.
getName();

// 5.
new Foo.getName();

// 6.
new Foo().getName(); 

// 7.
new new Foo().getName();
复制代码

解析

  • #1中.调用的是Foo上的静态方法. 打印值为: 2
  • #2中. 直接调用getName方法. 但是该方法定义了两遍, 一次是通过var函数表达式,一次是通过function来定义, 但是function的定义, 在解析时会前置. 所以var的函数表达式会覆盖function的定义. 打印值是4
  • #3中: Foo().getName(); 执行Foo()时, 会重写外层的getName方法, 由于Foo的返回值中并不包含getName方法. 所以会执行外层的方法. 打印值是1
  • #4中: 由于在#3中getName已经被覆盖. 所以这里的执行值也是 打印值是1
  • #5中: new Foo.getName(); 这里涉及到new和成员访问运算符的优先级问题. new(无参数列表)的优先级是18, 成员访问是19. 所以这里先执行的是getName, 后执行的new. 打印值是2
  • #6中. new Foo().getName(); 这里new后面带了(),所以优先级也是19. 这时从左到右执行. 先执行new Foo(), 后执行getName. 打印值是3
  • #7中. new new Foo().getName(); 这里有两个new, 第一个new使用的是无参数调用, 优先级是18, 第二个new后面是有参数调用, 优先级是19,成员访问. 优先级也是19. 所以这里的执行顺序是: 先执行第二个new, 然后成员访问, 然后第一个new. 打印值是3

运算符的执行优先级.

其他

如果描述或理解有误, 欢迎一起讨论.