博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
web前端经典小题
阅读量:5342 次
发布时间:2019-06-15

本文共 2145 字,大约阅读时间需要 7 分钟。

1.此题涉及的知识点众多,包括变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级等等。
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();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

答案如下:

Foo.getName();//2

getName();//4

Foo().getName();//1

getName();//1

new Foo.getName();//2

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

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

解析:先看此题,1.首先创建了一个Foo的函数,2.之后又为Foo创建了一个叫getName的静态属性存储了一个匿名函数,3.之后为Foo的原型创建了一个名叫getName的匿名函数。4.之后又通过函数变量表达式创建了一个getName的函数,5.最后再声明一个叫getName函。

第一问:自然是访问Foo上的静态属性,是2.

第二问:此处有两个坑,一是变量声明提升,二是函数表达式

以上问题代码可以等价于:

function Foo() {
getName = function () { console.log(1) };
return this;
}
function getName() { console.log(5) };//先提升函数声明
var getName;//然后提升变量,不会赋值
Foo.getName = function () { console.log(2) };
Foo.prototype.getName = function () { console.log(3) };
getName = function () { console.log(4) };
最后执行getName()时自然输出的是4.
 
第三问:先执行Foo(),首先在Foo函数的作用域里寻找变量getName,没有找到就到全局作用域里去寻找,找到了把getName重新赋值了一个匿名函数,最后返回的是window,相当于执行window.getName(),自然结果是1;
 
第四问:此时已经把变量getName存储了function () { console.log(1) }的匿名函数。所以结果为1;
 
后面的就牵扯到运算,优先级从高到底排序的,可以参考https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

 

第五问:点.的运算符高于new所以相当于new (Foo.getName());访问对象Foo的静态属性getName(),实际上把getName当作构造函数,结果为2;
 
第六问:
new Foo().getName(),括号()的优先级高于new,
相当于(new Foo()).getName();

构造函数的返回值

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

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

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

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

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

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

之后调用实例化对象的getName函数,因为在Foo构造函数中没有为实例化对象添加任何属性,遂到当前对象的原型对象(prototype)中寻找getName,找到了。

遂最终输出3。

第七问:
new new Foo().getName(),相当于new ((new Foo()).getName)();先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new;
 
参考:http://mp.weixin.qq.com/s/eO5hL0pcEHYr7jAbWTWAXg
 
 
 
 
 

      

转载于:https://www.cnblogs.com/youtian/p/7860095.html

你可能感兴趣的文章
php中eval函数的危害与正确禁用方法
查看>>
20172315 2017-2018-2 《程序设计与数据结构》第十一周学习总结
查看>>
MySQL添加、修改、撤销用户数据库操作权限的一些记录
查看>>
关于谷歌浏览器Chrome正在处理请求的问题解决
查看>>
Git核心技术:在Ubuntu下部署Gitolite服务端
查看>>
平面波展开法总结
查看>>
建造者模式
查看>>
ArraySort--冒泡排序、选择排序、插入排序工具类demo
查看>>
composer 安装laravel
查看>>
8-EasyNetQ之Send & Receive
查看>>
Android反编译教程
查看>>
List<string> 去重复 并且出现次数最多的排前面
查看>>
js日志管理-log4javascript学习小结
查看>>
Android之布局androidmanifest.xml 资源清单 概述
查看>>
How to Find Research Problems
查看>>
Linux用户管理
查看>>
数据库第1,2,3范式学习
查看>>
《Linux内核设计与实现》第四章学习笔记
查看>>
使用iperf测试网络性能
查看>>
图片的显示隐藏(两张图片,默认的时候显示第一张,点击的时候显示另一张)...
查看>>