尝试解析js面试题(一)

作者: 小pxu | 来源:发表于2016-05-23 21:53 被阅读2069次

说明:这是一道比较典型的综合考察js中作用域this指向对象解析顺序运算符优先级等概念的综合性考题;话不多说,先上题;

原作者解析:小小沧海(博客园)

function Foo() {
    getName = function () {
        alert (1); 
    };
    return this;
}
Foo.getName = function () {
    alert (2);
};
Foo.prototype.getName = function () {
    alert (3);
};
var getName = function () {
    alert (4);
};
function getName() {
    alert (5);
}

//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

解析:

1、Foo.getName(); //2

1)结果执行的是Foo对象的一个叫做getName()的属性,而1、4、5中的getName都是作为函数存在,所以可以排除1、4、5

2)剩下两个中,2是Foo对象自身的属性,3是Foo对象原型链上的属性,而自身属性的优先级高于原型链上的属性,所以执行结果是2

2、getName(); //4

1)结果执行的是getName函数,而题目代码中有3个相关函数,分别是1、4、5

2)1中的getName是定义在Foo函数中的函数,由于Foo尚未执行,因此它没有暴露出来,无法被外部调用,可以排除

3)4和5都可以被正常调用,关键在调用先后问题

4)由于5是普通函数(优先级最高),4是匿名函数;js解析时会将5提前至最上方优先解析,而后面解析的4会将5覆盖,所以执行结果是4

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

1)结果执行的是Foo函数,Foo函数中有个返回值是this;this被普通函数调用后,指向的对象一定是window对象,所以此处的结果已经可以解析为window.getName(),即调用getName()函数

2)由于window.getName()已经被修改为1,所以执行结果是1(??)

上面那句话是原作者的解释,此处还没理解透彻为什么1没有被2覆盖;下面举个例子对比下:

//第一个例子是题目的类型,不明为何上边fn1的结果未被覆盖??
function fn1 (){
    a = 1;
    return this
}
fn1()
var a = 2
console.log(fn1().a) //1

//第二个例子是我理解的会正常出现覆盖的情况
function fn1 (){
    a = 1;
}
fn1()
var a = 2
console.log(a) //2

4、getName(); //1

1)执行getName即是执行window.getName;所以执行结果同上题是1

5、new Foo.getName(); //2

1)此处考察到了运算符优先级的问题,就题目所需来看,成员访问".">new(带参数)>函数调用"()"(注意,"()"分为函数调用及优先运算两种,优先级是不同的;原作者开始的解释就出现了错误)

2)结果先执行Foo.getName(),结果同第一题为2;而new 2不会有任何变化,因此这里的结果也是2

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

1)从结果来看,应该理解成(new Foo()).getName()这样执行

2)根据成员访问".">new(带参数)>函数调用"()";成员访问优先执行,右侧是.getName()没问题

3)左侧分为两种可能:一种是new(带参数),即(new Foo());此处结果是构建一个函数

4)另一种是先执行Foo()函数后再将其结果new

5)因为new(带参数)>函数调用"()",所以是执行的(new Foo()),此对象Foo()自身没有getName这个属性,所以会向上追溯其原型链上的属性,即在此处执行了3;因此结果是3

//这里就是模拟new Foo()的结果
function F(){return this}
new F() //F {}

关于这点,原作者有解释如下(还是可以理解的):

构造函数的返回值

在传统语言中,构造函数不应该有返回值,实际执行的返回值就是此构造函数的实例化对象。

而在js中构造函数可以有返回值也可以没有。

1、没有返回值则按照其他语言一样返回实例化对象。

2、若有返回值则检查其返回值是否为引用类型。如果是非引用类型,如基本类型(string,number,boolean,null,undefined)则与无返回值相同,实际返回其实例化对象。

3、若返回值是引用类型,则实际返回值为这个引用类型。

原题中,返回的是this,而this在构造函数中本来就代表当前实例化对象,遂最终Foo函数返回实例化对象。

7、new new Foo().getName(); //3

1)这题我其实是懵逼的(懵逼脸😳)

2)求高手指教了 _ (:з」∠)_

还是贴下原作者解释,感觉有点不对

第七问, new new Foo().getName(); 同样是运算符优先级问题。

最终实际执行为:

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

先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new。

遂最终结果为3


最后,引用一张原作者提供的相当实用的运算符优先级表格(鼓掌)

运算符优先级--博客园

相关文章

  • 尝试解析js面试题(一)

    说明:这是一道比较典型的综合考察js中作用域、this指向、对象、解析顺序、运算符优先级等概念的综合性考题;话不多...

  • 尝试解析js面试题(二)

    说明:一共有13题(原本14题,最后一道什么鬼,嫌弃不要了),覆盖面比较广,都属于比较烧脑的类型,各种神坑;不过对...

  • 东哥面试题

    东哥面试题 ============ JS高级 1. 判断以下程序的输出结果: 答案: 100 50 解析: 构造...

  • js基础面试题

    面试题:延迟加载JS有哪些方式? 面试题:JS数据类型有哪些? 面试题:JS数据类型考题 考题一: 考题二: 面试...

  • react源码解析1.开篇介绍和面试题

    react源码解析1.开篇介绍和面试题 视频课程/demo 课程目录 怎样学习react源码 作为前端最常用的js...

  • HashMap 源码解析与面试题整理

    源码解析不会通篇解析,会通过面试题整理来针对性地解析其中的关键点 主要的几个面试题: HashMap的底层原理是什...

  • 前端相关大杂烩

    前端基础面试题(JS部分) 前端基础面试题(JS部分)学习 React.js 比你想象的要简单 原文地址:Lear...

  • 第3题-ES6代码转化为ES5的思路及实践

    面试题目: ES6 代码转成 ES5 代码的实现思路是什么? 示例: 答案解析: ES6作为JS的新规范,加入了很...

  • 第11题- 变量提升和函数提升

    面试题目(腾讯): 下面题目输出结果是什么? 答案解析: 这道题目主要考察JS的变量提升和函数提升相关的知识点 1...

  • golang 面试题

    Go面试题答案与解析

网友评论

    本文标题:尝试解析js面试题(一)

    本文链接:https://www.haomeiwen.com/subject/alzarttx.html