基于segmentfault上的一道题
题目
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);}
new foo.getName (); // 第一种
new foo().getName (); // 第二种
new new foo().getName (); // 第三种
-
首先先了解下优先级(由高到低)
由此可以知道new 的优先级带参数的比不带的高
解析
- 第一种
new foo.getName ();
'.'的优先级比new高
所以先执行foo.getName,在来执行new
也就是new (foo.getName) ()
// 返回一个foo.getName的实力 获得就是2 - 第二种
new foo().getName ();
主要犹豫的地方是先foo()函数运算还是先new
foo()先new (foo().getName)()
new 先(new foo()).getName()
如果new 不带参数的优先级确实比函数调用的优先级低,但现在new是带参数的所有优先级
所以执行的(new foo()).getName()
// foo()上的getName方法,但是没有这个方法所以去原型上找,结果为3 - 第三种
new new foo().getName ();
从上面分析得,new带参数会优先执行,这是在从左至右的运算基础下实现的
也就是第一步new (new foo().getName)()
第二步new ((new foo()).getName)()
最后进行运算 先计算new foo()
, 在获取getName,在对获取内容进行new ()计算
new ((new foo()).getName)()
也就是new (foo.prototype.getName)()
返回的就是3, 具体可以看下面new 原理解析
new原理
在第三种解析中我们要计算 new (foo.prototype.getName)()
的值,首先要明白new到底做了什么,其实就做了3件事
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
第一步:创建一个空对象
第二步:绑定该对象的原型
第三部:调用构造函数 // 执行了构造函数的内容
所以在 new (foo.prototype.getName)()
也就会返回foo.prototype.getName的一个实例,并且执行一次构造函数,也就是执行console.log(3)
,打印3这个结果