仍然对JavaScript的“this”感到困惑

仍然对JavaScript的“this”感到困惑,javascript,Javascript,在使用JavaScript对象时,我已经阅读了很多关于“this”关键字的文章,但我仍然有些困惑。我很乐意编写面向对象的Javascript,我通过引用完整的对象路径来解决“这个”问题,但我不喜欢我仍然觉得“这个”令人困惑的事实 我找到了一个很好的答案,这对我很有帮助,但我仍然不是100%确定。因此,我们来举个例子。以下脚本从test.html链接到 你期望看到的是什么 但我得到的是这个 我想我理解那里发生的一些事情,但如果有人向我解释,我会介意的 另外,我也不完全清楚为什么要调用第一个“con

在使用JavaScript对象时,我已经阅读了很多关于“this”关键字的文章,但我仍然有些困惑。我很乐意编写面向对象的Javascript,我通过引用完整的对象路径来解决“这个”问题,但我不喜欢我仍然觉得“这个”令人困惑的事实

我找到了一个很好的答案,这对我很有帮助,但我仍然不是100%确定。因此,我们来举个例子。以下脚本从test.html链接到

你期望看到的是什么

但我得到的是这个

我想我理解那里发生的一些事情,但如果有人向我解释,我会介意的

另外,我也不完全清楚为什么要调用第一个“console.log”?如果删除对init函数的调用//nick.name.init firebug仍然输出1。Window test.html,未定义。为什么呢?为什么加载html页面时,窗口对象会调用nick.name

非常感谢

另外,我也不完全清楚为什么要调用第一个“console.log”

在这里定义一个函数,立即调用它,并将其返回值{init:init}分配给nick.name

因此,执行是:

如果还没有一个变量具有非false值,则创建一个名为nick的变量 创建一个匿名函数… 在自己的作用域中创建一个名为helloA的变量 使用包含1的console.log按原样输出数据,该窗口是因为函数在全局上下文中而不是作为方法执行,而this.helloA window.helloA不存在。 定义一个名为init的函数 返回分配给nick.name的对象 然后调用nick.name.init,它在name的上下文中执行init函数。 这定义了helloB 然后它以2原样记录console.log,这个名称,还有这个.helloB nick.name.helloB-它不存在 所以您得到的第一个输出来自console.log'1',this,this.helloA

我认为您的主要问题是,您将调用方法的对象上的this.foo属性与函数可用的变量范围变量混淆

另外,我也不完全清楚为什么要调用第一个“console.log”

在这里定义一个函数,立即调用它,并将其返回值{init:init}分配给nick.name

因此,执行是:

如果还没有一个变量具有非false值,则创建一个名为nick的变量 创建一个匿名函数… 在自己的作用域中创建一个名为helloA的变量 使用包含1的console.log按原样输出数据,该窗口是因为函数在全局上下文中而不是作为方法执行,而this.helloA window.helloA不存在。 定义一个名为init的函数 返回分配给nick.name的对象 然后调用nick.name.init,它在name的上下文中执行init函数。 这定义了helloB 然后它以2原样记录console.log,这个名称,还有这个.helloB nick.name.helloB-它不存在 所以您得到的第一个输出来自console.log'1',this,this.helloA

我认为您的主要问题是,您将调用方法的对象上的this.foo属性与函数可用的变量范围变量混淆

这是在进行函数调用时根据每个函数定义的。当您将函数调用为o.f时,它将是函数中的o;当您将其调用为f时,它将是浏览器的全局对象,这是窗口。 您编写了nick.name=函数{…};右边部分的形状是f,因此是窗口

var foo=巴;定义一个局部变量。它可能不会像this.foo那样被访问,除非您在全局范围内,但这很愚蠢。要定义一个成员,通常需要编写以下代码:this.foo=bar;相反

这是在进行函数调用时根据每个函数定义的。当您将函数调用为o.f时,它将是函数中的o;当您将其调用为f时,它将是浏览器的全局对象,这是窗口。 您编写了nick.name=函数{…};右边部分的形状是f,因此是窗口

var foo=巴;定义一个局部变量。它可能不会像this.foo那样被访问,除非您在全局范围内,但这很愚蠢。要定义一个成员,通常需要编写以下代码:this.foo=bar;相反


如果你把它看作一个函数,而不是一个变量,那就简单多了。本质上,这是一个返回当前执行上下文的函数,即当前函数应用于的对象。例如,考虑下面的

function t() { console.log(this)}
这将返回非常不同的结果,具体取决于您如何调用它

t() // print window

bar = { func: t }
bar.func() // print bar

foo = { x: 123 }
t.apply(foo) // print foo

如果你把它看作一个函数,而不是一个变量,那就简单多了。本质上,这是一个返回当前执行上下文的函数,即当前函数应用于的对象。例如,考虑下面的

function t() { console.log(this)}
这将返回非常不同的结果 nt结果取决于您如何调用它

t() // print window

bar = { func: t }
bar.func() // print bar

foo = { x: 123 }
t.apply(foo) // print foo

这就是您的代码所做的:

它创建一个对象并指定给变量nick。 它创建了一个匿名函数。 它调用窗口范围中的函数。 它将包含init属性的对象的返回值指定给该对象的name属性。 它从init属性(方法委托)获取值,并调用该方法。 匿名函数执行以下操作:

它声明一个名为helloA的局部变量,并为其分配一个字符串。创建局部变量不会将其作为属性添加到当前对象。 它记录此窗口和不存在的helloA属性。 它创建一个匿名函数,并分配给局部变量init。 它使用属性init和局部变量init的值创建一个对象。 分配给init属性的匿名函数执行以下操作:

它声明一个名为helloB的局部变量,并为其分配一个字符串。创建局部变量不会将其作为属性添加到当前对象。 它从name属性(而不是nick变量)和不存在的helloB属性中记录该对象。
这就是您的代码所做的:

它创建一个对象并指定给变量nick。 它创建了一个匿名函数。 它调用窗口范围中的函数。 它将包含init属性的对象的返回值指定给该对象的name属性。 它从init属性(方法委托)获取值,并调用该方法。 匿名函数执行以下操作:

它声明一个名为helloA的局部变量,并为其分配一个字符串。创建局部变量不会将其作为属性添加到当前对象。 它记录此窗口和不存在的helloA属性。 它创建一个匿名函数,并分配给局部变量init。 它使用属性init和局部变量init的值创建一个对象。 分配给init属性的匿名函数执行以下操作:

它声明一个名为helloB的局部变量,并为其分配一个字符串。创建局部变量不会将其作为属性添加到当前对象。 它从name属性(而不是nick变量)和不存在的helloB属性中记录该对象。
Foo在这里不是函数,因此它没有apply方法。我想你是指t.applyfoo。apply方法允许您在调用函数时显式定义该函数的执行上下文值。另请参见Function.call JavaScript在这个意义上的灵活性可能是一个非常强大的工具,但它也是一个非常令人沮丧的来源,尤其是在你开始思考之前!谢谢你的回复。我能问问foo.applyt的事吗?那是个错误吗?应该是t.applyfoo//printfoo吗?很多Thanksfo在这里不是函数,所以它没有apply方法。我想你是指t.applyfoo。apply方法允许您在调用函数时显式定义该函数的执行上下文值。另请参见Function.call JavaScript在这个意义上的灵活性可能是一个非常强大的工具,但它也是一个非常令人沮丧的来源,尤其是在你开始思考之前!谢谢你的回复。我能问问foo.applyt的事吗?那是个错误吗?应该是t.applyfoo//printfoo吗?非常感谢Victor,这是一个很好的回答谢谢。你知道为什么window对象调用函数吗?确切地说,当你单独调用函数而不是作为成员调用函数时,这是全局对象,对于web浏览器来说是window。再次感谢Victor。非常感谢,维克多,回答得很好,谢谢。你知道为什么window对象调用函数吗?确切地说,当你单独调用函数而不是作为成员调用函数时,这是全局对象,对于web浏览器来说是window。再次感谢Victor。非常感谢。那么,当我将变量应用到一个对象(即this.helloA)时,我应该使用this关键字,还是这会使私有变量成为公共变量?@Nick:这取决于当前的上下文。如果上下文是对象,则可以使用this关键字访问该对象。如果它是默认的上下文窗口,您将向窗口对象添加属性,从而使它们成为全局/公共。那么,在将变量应用于对象(即this.helloA)时,我应该使用this关键字,还是将私有变量变为公共?@Nick:这取决于当前上下文。如果上下文是对象,则可以使用this关键字访问该对象。如果它是默认的上下文窗口,您将向窗口对象添加属性,从而使它们成为全局/公共的。它定义在lowman的范围内。给定范围中存在的变量与对象上的属性不同。非常感谢您的帮助。我花了一上午的时间创建了一些示例,我想我正在慢慢地理解它。我没有说它在lowman的上下文中定义了helloB。它定义在lowman的范围内。存在于g中的变量
iven范围与对象上的属性不同。非常感谢您的帮助David。我花了一上午的时间创建了一些示例,我想我正在慢慢理解。
function t() { console.log(this)}
t() // print window

bar = { func: t }
bar.func() // print bar

foo = { x: 123 }
t.apply(foo) // print foo