【问题标题】:JavaScript scope shifting - Help me understand [duplicate]JavaScript 范围转移 - 帮助我理解 [重复]
【发布时间】:2015-04-15 13:07:55
【问题描述】:

我正在创建一个程序,该程序最终将创建数千个小对象(理想情况下约为 60,000 个),每个小对象都包含特定信息。它将从一个小的 JSON 文件加载每个对象,该文件已经创建并位于服务器上的目录树结构中。

它如何找到文件对这个问题无关紧要(假设它超出了它的“范围”)但是我试图通过逐步了解程序的工作原理。

假设我也稍微简化了这一点;我知道你们中的许多人可能会发现我似乎在我的请求加载数据和实际加载数据之间添加了一个不必要的层(显然我可以通过 jQuery 的 $.getJSON().done()),但是因为有要考虑文件系统结构,程序也需要处理该部分。

Data = function() {

    var VERSION = 1.1;

    if (this.constructor === Data) {

        throw new Error("Objects may not be directly instantiated from an abstract class.");
    }
}

// Loads a file with the path from the root set in config.json

Data.prototype.loadData = function(treePath,callback) {

    // does data loading stuff here and proceeds through, eventually getting to this line: 
            callback(req,loadedData);

}

现在,我有一个抽象层 - 我不希望 Data 对象在其自身中创建,这就是为什么如果有人调用“new Data();”它会抛出错误。这是故意的。

然后我将拥有两个继承 Data 的对象;两者都具有以不同方式处理加载数据的方法。但是,由于两者的文件树结构相同,因此创建一个抽象对象来继承是有意义的。 (或者,作为一个子问题,对于 Data 对象的对象文字,这是一个很好的论据吗?)

现在,我从 FOO 调用 loadData,然后 Data 将调用位于 FOO 内部的 callack。我尝试将其声明为 FOO.prototype.pareseData 和 FOO.parseData,这没有区别。

FOO.parseData = function(req,path) { 

    // Parse the data and deal with it as needed.
}

单步执行,当我从主程序调用 FOO 并告诉它开始加载数据时,我可以看到“this”值。最初,this = FOO,正如预期的那样;在 Data 调用回调函数之前,这将保持 FOO。

一旦代码命中 FOO.parseData,它就会从 FOO 变为“窗口”。

我不知道为什么...?

【问题讨论】:

  • FOO 是什么?我没有看到它在任何地方定义
  • 文字多的时候,人们抱怨它,文字太少的时候,人们抱怨它......
  • RGraham - 假设 FOO 已正确声明和实例化。我把它省略了,因为除了几行额外的代码之外,它并没有给问题增加太多。
  • @StevenC.Britton (S)他只是指出,如果你简洁的话,你会在 Stack Overflow 上获得更多帮助。这是一个事实,基于他在这个网站上的时间和他们获得的经验。您可以忽略这一点,但不要将其视为对您写作技巧的个人侮辱。
  • 是的,创建一个加载器函数,通过将数据位传递给相应的构造函数来执行服务器请求并构造FooBar 实例。如果您的 foos 和 bar 不共享任何通用方法,那么它们甚至不需要超类,但您对此有点模糊。而不是向您的服务器发出 60000 个请求,您绝对应该捆绑文件(可能是在服务器端动态地)并且只发出几个大请求。

标签: javascript oop scope


【解决方案1】:

那是因为在 javascript 中,“this”是对当前范围的引用,因此,如果您在原始范围之外调用函数/回调,则“this”很可能是“窗口”,因为“窗口”是调用函数/回调的那个。

为了将“this”保持在您想要的范围内,您必须在声明它时将您的函数绑定到该给定范围:

function Foo() {
    this.bar();
}.bind(this); //-> Here you bind Foo to the current scope, so inside Foo, this will be always the scope where it was bound.

【讨论】:

  • this 不指范围!虽然它们是相关的,但它们是不同的东西。
  • @FelixKling 谢谢你,菲利克斯。 “this”指的是对象本身,本质上是我们正在工作的范围。将其称为“上下文”或任何您想要的名称,我知道我们可能需要清楚地定义这样的事情。好吧,所以我是游戏新手……忍耐一下,k? ;)
  • @Steven:当然,在与他人交流和尝试教学时,使用正确的术语至关重要 :) 而“范围”在编程语言中具有非常特定的含义。它描述了变量可见的“区域”。 this 不是范围。它不允许您访问范围内的变量(例外是全局范围,因为在 JS 中全局变量是全局对象的属性)。通常局部变量不是对象的属性。
  • 我将把它标记为答案,因为它为我提供了一些我可以使用的好信息。提供的链接可能有用,但由于这是关于提问和获得答案的,所以这个链接最适合。
  • 很高兴我能帮助你,至少提供一些有用的信息:)
【解决方案2】:

我强烈推荐你阅读这篇文章。

http://ryanmorr.com/understanding-scope-and-context-in-javascript/

您的问题在第 3 段中进行了解释 - 什么是“this”上下文

“上下文通常由函数的调用方式决定。当函数作为对象的方法调用时,this 设置为调用该方法的对象:

var obj = {
    foo: function(){
        alert(this === obj);    
    }
};
obj.foo(); // true

同样的原则也适用于使用 new 操作符调用函数来创建对象的实例。以这种方式调用时,函数范围内的 this 的值将被设置为新创建的实例:

function foo(){
    alert(this);
}
foo() // window
new foo() // foo

当作为未绑定函数调用时,这将默认为浏览器中的全局上下文或窗口对象。但是,如果函数在严格模式下执行,上下文将默认为未定义。”

【讨论】:

  • 为了保持网站的质量,如果您能从其他资源中引用您认为重要的部分会更好。仅链接的答案不是很可靠,因为链接可能会损坏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 2014-03-10
相关资源
最近更新 更多