JavaScript类和调用上下文
有人能帮我解释一下为什么第一个例子有效,而第二个却不行 例1: 输出:JavaScript类和调用上下文,javascript,class,object,closures,Javascript,Class,Object,Closures,有人能帮我解释一下为什么第一个例子有效,而第二个却不行 例1: 输出: Hello foo Hello foo Hello foo Hello undefined 例2: 输出: Hello foo Hello foo Hello foo Hello undefined 我猜是因为第一个示例使用闭包,所以它保留了对name局部变量的引用,但第二个示例不是,并且由于调用greeting()方法时没有对象上下文,它默认为undefined此的解析延迟到JavaScript中的执行时间 通过将
Hello foo
Hello foo
Hello foo
Hello undefined
例2:
输出:
Hello foo
Hello foo
Hello foo
Hello undefined
我猜是因为第一个示例使用闭包,所以它保留了对
name
局部变量的引用,但第二个示例不是,并且由于调用greeting()
方法时没有对象上下文,它默认为undefined
此的解析延迟到JavaScript中的执行时间
通过将foo.greeting
设置为greeting
,然后执行greeting()
,您正在全局上下文中执行greeting()
;其中,此
指向窗口
,除非您是在严格模式下运行,而不是您的Foo
实例。因此,在greeting()
中,它正在查找窗口;并返回未定义的。
有关更详细的说明,请参见。在JavaScript中有四种调用函数的方法,每种方法都会更改函数中此
的值:
作为一个全局函数调用:greeting()
。此
的值是全局窗口
对象(在浏览器中)
作为某个对象上的方法:foo.greeting()
。this
的值是
操作符(foo
)左侧的对象实例
作为构造函数:新问候语()
。this
的值是一个新对象,它是由函数创建并隐式返回的。这用于创建新对象
使用呼叫
或应用
:问候语。应用(someVal,someArgs)
。this
的值是作为第一个参数传递的对象(someVal
)
任何函数都可以用这四种方式中的任何一种执行(尽管并非所有函数都应该用其中一些方式执行)
在第一种情况下,您正在执行方法调用:
var foo = new Foo('foo');
foo.greeting();
…因此,此
是函数内部的foo
。在第二种情况下,您正在执行全局函数调用:
var greeting = foo.greeting;
greeting();
…因此此
是函数内部的窗口
Edit:注意@jAndy的回答,该回答指出了本例中更突出的问题,即在第一个示例中,问候语
结束于自我
(无论如何调用),但在第二个示例中不结束(这使得函数的调用方式相关)。第二个问候语()在全局作用域上执行,因此相应地,此
是窗口对象(与执行函数的作用域相同,window.name
随后未定义)。如果您通过apply()
或call()
传递上下文,它将再次工作,例如
var greeting = foo.greeting;
greeting.apply(foo);
许多答案都包含有用且正确的信息,但没有一个能正确解释行为
在第一个示例中,它只记录两次Hello foo
,因为您正在创建一个变量self
,该变量引用此
对象。然后,该self
变量将在问候语函数中关闭。因此,您可以随意调用该函数,它总是访问self.name
,而不是this.name
,因此它总是一样的
在原型
示例中没有这样做。在这里,您可以直接访问this.name
,然后了解如何调用该函数非常重要(请参见@lwburk answer)
所以再说一遍,即使你把第一个例子叫做
foo.greeting.call( window );
它仍将访问closuredself
变量并记录Hello foo
了解有关此的更多信息:。。。然后@Matt-非常正确,尽管bind
不调用函数;它创造了一个。它无论如何也不能回答OPs的问题。@jAndy-Hah!所以它没有。好主意。@jAndy-留下我的答案只是因为它仍然与OP的第二个例子有关。此外,还添加了一条指向您的答案的注释。它也不能回答OPs问题。