rea*_*ess 4 javascript closures class object
有人可以帮我解释为什么第一个例子有效,但第二个例子没有.
// Define a class
function Foo(name) {
var self = this;
this.name = name;
this.greeting = function() {
console.log('Hello ' + self.name);
}
}
var foo = new Foo('foo');
foo.greeting();
var greeting = foo.greeting;
greeting();
Run Code Online (Sandbox Code Playgroud)
输出:
Hello foo
Hello foo
Run Code Online (Sandbox Code Playgroud)
// Define a class
function Foo(name) {
this.name = name;
}
// Greeting
Foo.prototype.greeting= function () {
console.log('Hello ' + this.name);
}
var foo = new Foo('foo');
foo.greeting();
var greeting = foo.greeting;
greeting();
Run Code Online (Sandbox Code Playgroud)
输出:
Hello foo
Hello undefined
Run Code Online (Sandbox Code Playgroud)
我的猜测是因为第一个例子是使用闭包,所以它保留了对name局部变量的引用,但第二个例子不是,因为greeting()在没有对象上下文的情况下调用方法,所以它默认为undefined.
许多答案,都有有用和正确的信息,但没有一个能正确解释行为.
在第一个示例中,它只记录Hello foo两次,因为您正在创建一个self引用该this对象的变量.那个self变量然后在你的关闭greeting function.因此,您可以根据需要调用该函数,它将始终访问,self.name而不是this.name始终相同.
你不要在你的prototype例子中这样做.在那里,你直接访问this.name,然后它是的确很重要如何将调用该函数(见@lwburk答案).
所以,即使你把第一个例子称为
foo.greeting.call( window );
Run Code Online (Sandbox Code Playgroud)
它仍然可以访问闭包self变量和日志Hello foo.
有四种方法可以在JavaScript中调用函数,每种方法都会更改this函数内部的值:
作为全球函数调用:greeting().值this的全局window对象(在浏览器中).
作为某种对象的方法:foo.greeting().值this是.operator(foo)左侧的对象实例.
作为构造函数:new greeting().值this是一个新对象,它是从函数中创建并隐式返回的.这用于创建新对象.
使用call或apply:greeting.apply(someVal, someArgs).值this是作为第一个参数传递的对象(someVal).
任何函数都可以用这四种方式中的任何一种来执行(尽管并非所有函数都应该在其中一些函数中执行).
在第一种情况下,您正在执行方法调用:
var foo = new Foo('foo');
foo.greeting();
Run Code Online (Sandbox Code Playgroud)
...所以this是foo在函数内部.在第二种情况下,您正在执行全局函数调用:
var greeting = foo.greeting;
greeting();
Run Code Online (Sandbox Code Playgroud)
...所以this是window在函数内部.
编辑:请注意@ jAndy的答案,指出在这种情况下,更突出的问题,这是greeting关闭了self在第一个例子(不管它怎么叫),但在第二个没有做(这则使得如何调用该函数相关).