看代码输出
// a
function Foo () {
getName = function () {
console.log(1);
}
return this;
}
// b
Foo.getName = function () {
console.log(2);
}
// c
Foo.prototype.getName = function () {
console.log(3);
}
// d
var getName = function () {
console.log(4);
}
// e
function getName () {
console.log(5);
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
- 函数、变量声明会被提升,上述代码相当于:
// a
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);
};
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
-
Foo.getName(); //2直接获取函数的属性getName 输出2;
-
getName(); // 4底部表达式getName = function(){}输出了4;
-
Foo().getName(); // 1调用了Foo()函数返回了一个返回值this,指向window,该函数内部getName变量不适用var、let声明,暴露成了全局对象,所以window.getName()输出1;
-
getName(); // 1由于第3步,暴露了一个全局对象getName();,所以此处执行Foo()里的getName()输出1;
-
new Foo.getName(); // 2执行执行Foo的上的getName属性,输出2;
-
new Foo().getName(); // 3new了一个Foo构造函数的实例,并且执行getName,由于实例上没有,就去找原型链上继承来的Foo.prototype.getName,因此输出3;
-
new new Foo().getName(); // 3new了两次,但是new Foo().getName()并没有返回值,因此第二次new没有输出,还是找原型链上继承来的Foo.prototype.getName,因此输出3;
其他
属性上声明的变量会放在Person.prototype.constructor对象上(无需继承),原型对象上声明的变量,直接暴露在与constructor同级上,如下: