此题涉及的知识点:声明提升和提升优先级、构造函数返回值问题、js运算符优先级、实例化对象的属性访问优先级、逻辑运算符运算
题目:
// 方式1:创建了一个有返回值的构造函数,在里面定义了全部变量getName指向一个匿名函数(小心闭包)
function Foo() {
getName = function () {
console.log(1);
}
return this;
}
// 方式2:构造函数的一个属性getName指向一个匿名函数
Foo.getName = function () {
console.log(2);
}
// 方式3:构造函数的原型上有个getName方法
Foo.prototype.getName = function () {
console.log('baidu' && 'google');
}
// 方式4:定义一个变量getName指向一个匿名函数
var getName = function () {
console.log(4);
}
// 方式5:声明一个叫getName的具名函数
function getName() {
console.log(5);
}
// 输出结果
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
// 2 4 1 1 2 "google" "google"
第1问 - - Foo.getName()
即运行方式2,故得结果2
第2问 - - getName()
直接调用getName函数,关乎方式4和5
由于函数声明提升,在预编译时方式5会提升到上面去,同时方式4是变量的赋值, 所以, 该变量会覆盖函数getName,方式4会覆盖方式5,故得结果4
第3问 - - Foo().getName()
先执行Foo函数,然后调用Foo函数的返回值对象的getName方法
Foo函数中定义了全局变量getName指向一个匿名函数,即改变了window上的getName值;Foo()返回的this指向window对象
即window.getName(),故得结果1
第4问 - - getName()
直接调用getName函数,即window.getName(),亦得结果1
第5问 - - new Foo.getName()
根据js运算符优先级:new ( Foo.getName )()
将Foo.getName作为构造函数,然后执行它,故得结果2
第6问 - - new Foo().getName()
根据js运算符优先级:( new Foo() ).getName()
知识点1:传统意义上,构造函数是没有返回值的,执行后结果为创建出来的实例对象
js中构造函数既可以有返回值也可无返回值
1. 无返回值时,执行后结果为实例对象
2. 有返回值时,若返回值是基本类型,则相当无返回值,执行结果为实例对象
若返回值是引用类型,执行结果为该引用数据
本问中Foo函数执行后返回this,而this在构造函数中指向实例对象,层层往上找getName方法
属性访问优先级:对象自身 > 构造函数 > 原型 > 父级,故运行方式3
知识点2:逻辑运算符运算 - - 对于"&&“来说,如果前者为真,那么就执行后者,否则只执行前者;
对于”||“来说,如果前者为真,只执行前者,后者不必执行,否则还得执行后者。因此结果为"google”。
第7问 - - new new Foo().getName()
根据js运算符优先级:new ( ( new Foo() ).getName )()
先执行new Foo(),再得到new Foo().getName作为构造函数,然后执行它,得到结果"google"