一道综合面试题(原型、this、作用域、构造函数、运算符优先级)
amandakelake opened this issue · comments
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();
function Foo() {
getName = function () { alert (1); };
return this;
}
// 为Foo创建了一个叫getName的静态属性存储了一个匿名函数
Foo.getName = function () { alert (2);};
// 为Foo的原型对象新创建了一个叫getName的匿名函数
Foo.prototype.getName = function () { alert (3);};
// 通过函数变量表达式创建了一个getName的函数
var getName = function () { alert (4);};
// 通过函数声明一个getName函数,注意提升,所以getName最后应该是上一行的4
function getName() { alert (5);}//提升
//请写出以下输出结果:
Foo.getName(); //2 Foo上面的静态属性
getName(); // 4 当前上文作用域内的叫getName的函数,所以跟1 2 3都没什么关系,但函数声明被提升了 所以函数表达式在后
Foo().getName(); // 1
// Foo函数的第一句 getName = function () { alert (1); }; 是一句函数赋值语句,注意它没有var声明
// 所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,找到了,这时候是4,然后赋值为1
// 此处实际上是将外层作用域内的getName函数修改了
// 此处若依然没有找到会一直向上查找到window对象,若window对象中也没有getName属性,就在window对象中创建一个getName变量
// 此时,Foo返回了this,如果函数独立调用,那么严格模式下该函数内部的this,则指向undefined,现在是非严格模式,所以指向window
// Foo函数返回的是window对象,相当于执行 window.getName() ,而window中的getName已经被修改为alert(1),
getName(); // 与上一问相同,已经被改为1了
new Foo.getName(); //2
// 这里考察运算符优先级
// 圆括号 > (成员访问.号 > new) > 函数调用 > 其他(具体再看)
// 这里成员访问.号优先级高于new 相当于 new (Foo.getName)() 相当于将getName()函数当做构造函数,这个构造函数现在是foo的静态属性2
new Foo().getName(); //3
// 相当于 (new Foo()).getName()
// 这里构造函数Foo返回了实例化的对象,然后去原型对象中找到的getName, (Foo.prototype.getName = function () { alert (3);};)
new new Foo().getName(); // 3
// new ((new Foo()).getName)();
// 先初始化Foo的实例化对象,然后将其原型上的getName函数作为构造函数再次new。
构造函数的返回值
构造函数可以有返回值也可以没有
- 没有返回值则按照其他语言一样返回实例化对象。
- 若有返回值则检查其返回值是否为引用类型。如果是非引用类型,如基本类型(string,number,boolean,null,undefined)则与无返回值相同,实际返回其实例化对象。
- 若返回值是引用类型,则实际返回值为这个引用类型。
如果返回this,而this在构造函数中本来就代表当前实例化对象,遂最终Foo函数返回实例化对象