web前端经典小题

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
 
 
 
 
 

      

posted @ 2017-11-19 16:04  YouTianZhao  阅读(289)  评论(0编辑  收藏  举报