js预解析
案例一:
1 function Foo(){ 2 getName = function(){ alert(1);}; 3 return this; 4 } 5 Foo.getName = function(){ alert(2);}; 6 Foo.prototype.getName = function(){ alert(3);}; 7 var getName = function(){ alert(4);}; 8 function getName(){ alert(5);}; 9 10 // 请写出下列的输出结果 11 Foo.getName(); 12 getName(); 13 Foo().getName(); 14 getName(); 15 new Foo.getName(); 16 new Foo().getName(); 17 new new Foo().getName();
按代码执行顺序,先进行预解析,即变量和函数的提升。
1 function Foo(){ 2 getName = function(){ alert(1);}; 3 return this; 4 } 5 var getName; //该getName会被第六行的getName覆盖 6 function getName(){ alert(5);}; //该getName会被第9行的getName覆盖 7 Foo.getName = function(){ alert(2);}; 8 Foo.prototype.getName = function(){ alert(3);}; 9 getName = function(){ alert(4);};
解析完后的代码
1 function Foo(){ 2 getName = function(){ alert(1);}; 3 return this; 4 } 5 Foo.getName = function(){ alert(2);}; 6 Foo.prototype.getName = function(){ alert(3);}; 7 getName = function(){ alert(4);};
第一问:Foo.getName(); //2
找到Foo这个构造函数(也是个对象),调用它的静态方法
第二问:getName(); //4
预解析后 getName = function(){ alert(4);};
第三问:Foo().getName(); //1
调用Foo这个构造函数,调用就会执行Foo内部的代码,该局部作用域也会进行预解析,执行到getName时,发现他没有进行声明,就会去全局下找有没有这个getName,
如果没有就声明一个,如果有就会重新赋值。所以此时,getName = function(){ alert(1);};
return this, 函数内部的this具体指谁,要看调用它的是谁就是看.前面是谁。Foo()其实省略了window.Foo();因此this指向window
最后变成了window.getName(); 也就是被重新赋值后的getName 。是1
第四问: getName(); //1 经过第三问的分析,此时window.getName = function(){ alert(1);};
第五问: new Foo.getName(); //2
整理下优先级:new (Foo.getName()); 先调用Foo的静态方法,就变成 new (function(){ alert(2);};)()
了解下new过程会做些什么
1、创建空对象;var obj = {};
2、设置新对象的constructor属性为构造函数的名称,设置新对象的__proto__属性指向构造函数的prototype对象;
obj.__proto__ = ClassA.prototype;
3、使用新对象调用函数,函数中的this被指向新实例对象:
ClassA.call(obj); //{}.构造函数();
4、返回新对象obj
原文:https://www.cnblogs.com/xiaoyue-/p/10653949.html