写这篇博客的原由是因为昨日的凡科笔试遇到了类似的题目。
现在就来看看这道题目,首先正如注释写的那样,因为存在函数提升所以第一个getval()的输出就是5,接着调用f.getval这个函数输出2,
f().getval()这一步的理解是比较重要的:
第一步:先执行f函数内的代码;因为f函数里的getval没有用var等声明,所以getval变为了全局的函数而不是f函数的私有成员,接着返回this=》即window对象;
第二步:这时f().getval()变成了window.getval();所以输出为1
第二个getval的调用:参照上面故也输出1;
new f.getval():因为成员访问'.'的优先级比new高,所以先执行f.getval,在来执行new,可看成=》new (f.getval) (),new返回f.getval的实例,输出2;
new f().getval():这里主要犹豫的时先执行f()还是new,因为此时new是带参数的,所以先new,=》(new f()).getval,即调用的是f()上的getval,因为在f()里没找到自己的getval,所以去原型上找,输出为3
new new f().getval(): 由上面就可以知道带参数的new会优先执行故:
第一步:new( new f().getval)()
第二步:new( ( new f() ).getval)()
先计算new f()
, 在获取getval,在对获取内容进行new ()计算,再进行调用;
也就是new( ( new f() ).getval)() =》new(f.prototype.getval)(),故输出为3.
参考文章:https://www.jianshu.com/p/412ccd8c386e
补充:
静态方法和实例方法:
function f(){ getval = function(){ console.log(1) } return this; } //这是f的静态方法 f.getval = function(){ console.log(2) } //这是f的实例方法 f.prototype.getval = function(){ console.log(3) }
当我们希望某个方法只有构造函数自身可以使用,实例无法继承使用,此方法就应该使用静态方法。
函数f无法直接调用实例方法,实例也无法直接调用静态方法。
变量提升:
var getval = function(){ console.log(4) }; function getval(){ console.log(5) } //相当于 function getval(){ console.log(5) } var getval ; getval = function(){ console.log(4) };
函数和变量都存在提升,但是函数提升优先级高于变量提升,且不会被同名变量声明时覆盖,但是会被变量赋值后覆盖