/ js

js中new、prototype、function提升问题

在一个前端面试题中发现几个概念,虽说面试题考的一般都不太容易在工作中遇到,但掌握这些对于debug、阅读代码、有时理解原理有帮助,原文在这里,直接去原文看也不错。

执行结果都是弹出alert。虽然也写了不少js,但和oo相关的概念并没有弄清楚,借着这个题能掌握一些。

在js中一个function可以被直接调用,也可能被new,而后者显然是oo中的东西,好像在java中常见。一个functionnew,这个function就被看作是oo中class的构造函数,会返回一个object,如果function中有this.field_name=name之类的语句,产生的object中就会有field_name这个属性,同时有一点需要注意的是,即便是new,也相当于执行了这个function一次,所以里面其他的操作也都是执行过了的,并不只是生成了object和设置了各种属性。另外,如果作为构造函数,不应该有返回值,但js就是允许有,如果有的话,返回基本类型的值,比如Number或者String相当于没返回,但如果返回了一个object,那就会用返回值,而不是创建一个空的object再把相应属性设置上返回这个。

要分析这个题目,又不得不说起来js中的this,这是一个神一般的变量,这里不打算详细描述,如果涉及到会说明一下,如果不了解可以搜索看看,有不少相关信息。

js中可以给一些对象添加额外的属性,比如题目中给Foo添加了getName,值是一个function,当访问Foo.getName()的时候就是访问Foo上的getName方法,类似class的静态方法,属于class,第一问是alert(2)。

那么直接调用getName()是怎样呢?会从js全局空间中寻找getName函数,因为这段代码外面并没有一层作用域了,所是是最外层,在全局空间中寻找,也就是之前定义的getName方法。竟然有两种定义getName的方法:把匿名函数赋值给变量、直接定义函数。也就是面试题会这样考,实际代码中为了可读性怎么也不会这样写来考验开发者智慧。js中每个作用域中的用function关键字定义的函数,都会在代码执行前被提到作用域最前面,所以即便是写在了最后的function xx(){},如果在最前面有调用,也是正常的;但如果是把匿名函数赋值给变量则是在运行到这一行代码时才被执行,所以这里的getName实际是alert(4)而不是alert(5)。

下一问Foo().getName(),首先需要得到Foo()的返回值,是神一般的this,在全局空间中,this指向window(如果是浏览器的话,非static mode,不明白可以自己查询),不出意外的话是上一问的alert(4),但执行了Foo后全局空间中的getName被Foo中的语句修改了,所以这一问是alert(1)。

此时getName刚刚被Foo调用修改调,所以是alert(1)。

下一问的new也变成了神一般的变量,题目在考察操作符的优先级。。。这个东西一般是大致扫一眼,根本不太会细看,况且即便细看都不一定能作对这里的题:new Foo.getName()的执行顺序是:(new Foo.getName)(),在js中new有两个优先级,一个是带参数的,一个是不带的,比如new Foo()是带参数的,而new Foo是不带的,带参数的优先级更高一点。你以为这里的括号是getName的么,根本不是,而是new的。

后面几问含义都差不多了。

对我来说题目已经相当难了,但原文作者又丧心病狂增加了两处难度(具体看原文最后),假使真用这种题目面试前端,恐怕通过率非常低,真正明白其中道理的更少。所以面试主要考察的是应试者的分析思路,至于答案,对了当然好,但思路说不上来的话,恐怕是做题背的吧?

说到这里,我想到面试中,不应该总考察学术性很强的题目,而更应该偏重实践,比如让你来为某个功能设计解决方案,设计好后可以交流一下是怎么做的,一步一步由外到内,可以问得很细,同时可以看到应试者实际解决问题的能力而不是背题的能力,毕竟招人来是解决业务问题的而不是做题的。与应试者的交流过程中,可以了解到他是如何思考问题的、对业务是否熟悉、对技术掌握的深度到底有多少、非理想环境中如何trade-off以及理由是什么,其实能得到的信息很多,远比做题得到的信息多得多。

那么难道完全不需要考虑编码能力吗?当然需要,但需要精心设计方法来考察而不单是用数学题筛选,我猜如果是算法工程师职位,更不会用数学题来面试了,应当是对某些算法的深入理解、原理性、拓展性的考察吧。

又扯远了!