详细说一下这道js面试题

2016-12-16

今天面试遇到的一个问题,关于js的基本语法问题,因为我做错了,所以这种题目很无聊,额…严肃的说,其实这道题还是考察了挺多东西的,所以还是要拿来说说

先看题目

1
2
3
4
5
6
7
function Dog() {
a = function() {console.log('1')};
}
Dog.a = function() {console.log('2')};
Dog.prototype.a = function() {console.log('3')};
var a = function() {console.log('4')};
function a() {console.log('5')}

下面代码会输出什么:

1
2
3
4
5
6
7
a();
Dog.a();
a();
Dog.a();
new Dog.a();
new Dog().a;
new new Dog().a;

先来看下这道题考查的点:

  • 抗压能力
  • 函数式声明提升
  • 变量作用域
  • 全局变量
  • js运算符优先级
  • 构造函数
  • new关键字
  • prototype方法

分析下题目

1
2
3
4
5
6
7
8
// 一个构造函数
function Dog() {
a = function() {console.log('1')}; // 这里的a是全局变量
}
Dog.a = function() {console.log('2')}; //Dog虽然是个构造函数,但函数本质上也是对象,挂个属性没毛病 (但平时不会这么写代码)
Dog.prototype.a = function() {console.log('3')}; // 这是正常给构造函数挂个方法,实例对象会用到这个方法
var a = function() {console.log('4')};
function a() {console.log('5')} // 函数式声明会整体提升的

一个一个来

第一题

为了简单说明,下面用a函数输出的数字来代表a分别是哪个a

因为5这个函数式声明,函数式声明会被提前至外部脚本或外部作用域顶部,所以5是最先被定义的

然后来看1里的a,没有var,是全局变量,相当于a在第一行声明,不过因为有5的存在(已经声明并且定义),这个声明就是指向5的

2和3都是Dog的作用域下,和这个无关

代码分析到这里为止的话, a(); 结果应该是5

因为4这里a被重新赋值,所以 a(); 结果是4

第二题

Dog虽然是构造函数,它也是个函数,但首先它是一个对象

就好比你是小学生,小学生也是学生,但首先你是一个人

所以Dog在这里就是对象,a就是它的一个属性而已,而这个属性是个方法,()执行这个方法,所以结果是2

第三、四题

第三题和第四题问的一样,如果我还是小学生的时候,我就会举手问老师:老师这个题是不是出错了?

但是从以往的面试题来说这里一定是个陷阱,因为a()执行了一次,再执行一次的话。。。。。。。。。。他妈的不还是一样,函数体内都是写死的东西啊,Dog.a()同理,不过面试高度紧张的时候,往往就不敢相信这是道送分题啊

第五题

1
new Dog.a();

看到new的时候,Dog作为一个构造函数应该在感慨终于轮到我登场了,然而现实却狠狠的打了它的脸。因为 .的优先级是高于new的,

属性访问表达式和调用表达式的优先级比所有的运算符都要高

所以被new的是Dog.a,而Dog.a是一个普通的函数,但是我们要知道构造函数是一种约定的名称,事实上任何函数都可以被new出一个对象,只是这种对象没什么卵用

那么久要看new这个过程到底发生了什么, 有兴趣可以参考旧文

Javascript中的new关键字

这里只说一点,new的时候,被new的函数会执行,所以这就和第二相同,结果是2

第六题

1
new Dog().a;

如果没有第五题,这道题没什么特别的,但是经历第五题的各种优先级问题,你会怀疑自己,到底哪个先执行啊

首先(),[],.这个是最高优先级同级的,谁靠左边,最先执行

所以这里先不管.a,那么就是new Dog(),这个的结果是让身为构造函数的Dog表示很欣慰,终于new出个正儿八经的对象了,

这个对象有一个方法,没错就是挂在其构造函数Dog的prototype上的a

所以这个执行的结果是没有console任何东西,这个a还没执行

第七题

1
new new Dog().a;

第六题明白了,这道题就是送分题了,再加一个new,优先级当然是在最后了,执行过程同下

1
new ((new Dog()).a)

第六题的结果是a这个函数,普通函数呗new,就一定有函数被执行的过程,那么a执行就会打印出3

总结

其实这种问题,做错也没什么,人的记性毕竟有时候就是不太可靠,但是分析过程要懂,说白了就是看着参考答案你要说的出来为什么,如果语法不过关是做不到这点