function Foo(){ getName = function () {alert(1);} return this; } Foo.getName = function() {alert(2);}; Foo.prototype.getName = function(){alert(3);}; var getName = function(){alert(4);}; function getName(){alert(5)}; Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();
2 ----Foo.getName(); 4 ----getName(); 1 ----Foo().getName(); 1 ----getName(); 2 ----new Foo.getName(); 3 ----new Foo().getName(); 3 ----new new Foo().getName();
为了阅读效益最大化,请先了解执行环境
和变量对象
的文字性
概念。html
执行环境
挺常见的,它是长这样的。它的特性是先进后出(stack)。函数
上述图片是来源于代码执行到Foo( ).getName( )。this
(anonymous function) 其实就是global context
spa
表示方法:prototype
ECStack = [ functionContext(Foo), /*这不是函数*/ GlobalContext ]
变量对象
也挺常见,在Chrome中长这样。指针
表示方法一般是:code
//以上述代码还没有执行时为例 VO = { Foo: { <reference to function>, return this } getName: <reference to function> }
代码执行有两个阶段htm
进入环境(代码未执行,已编译)对象
代码执行blog
如今一块儿来看看每一行代码的执行
上述代码未执行时,变量对象是这样的。
VO = { Foo: { <reference to function>, return this } getName: <reference to function(){alert(5)}> }
该行代码执行后VO会变成这样。
VO = { Foo: { <reference to function>, getName: <reference to function() {alert(2)}, return this } getName: <reference to function(){alert(5)}> }
VO的Foo图示是这样的
该行代码执行后VO会变成这样。
VO = { Foo: { <reference to function>, getName: <reference to function() {alert(2)}, prototype: { getName: <reference to function(){alert(3)} }, return this, } getName: <reference to function(){alert(5)}> }
VO的Foo图示是这样
该行代码执行后VO会变成这样。
VO = { Foo: { <reference to function>, getName: <reference to function() {alert(2)}, prototype: { getName: <reference to function(){alert(3)} }, return this } getName: <reference to function(){alert(4)}> }
直接去VO里寻找结果发现alert 2。
getName() //等于 window.getName();
一样直接在VO里能够直接找到答案 alert 4。
这里比上述多了一个函数调用,Foo()调用返回this(指向window),因此此时
Foo().getName(); //等于 window.getName()
同时注意:
因为Foo()调用,致使VO发生了变化。最后alert 1.
VO = { Foo: { <reference to function>, getName: <reference to function() {alert(2)}, prototype: { getName: <reference to function(){alert(3)} }, return this } getName: <reference to function(){alert(1)}> }
结果同上
最后三问考察了new、属性访问符、及函数调用优先顺序和new运算符的做用。
优先顺序
参考以下,或点这
不管是用哪一种属性访问表达式,在"."和"[]"以前的表达式老是会先计算的。
对于new Foo.getName()
来讲,点运算级最高,因此先进行计算表达式
Foo的值。若是先运算new的话,就证实了new优先级高于点号,与规范不和。
而对于new Foo().getName()
来讲,Foo()与new Foo()相比,new优先级更高,因此先算new Foo(),new出来的新对象继承
了Foo.prototype属性,所以新对象访问getName时会弹出3.
此处要明白new的做用
建立新的空对象
将新对象继承构造函数的prototype属性,并调用构造函数初始化
将构造函数的this指针指向新建对象。
最后一个问题同理倒数第二个。
谢谢ID:李卫
的提醒。