javascript:功能范围

时间:2013-01-03 16:05:51

标签: javascript

如果函数有范围,它们应该在该范围内执行,但在这里我认为它不同。查看代码

  function foo() {
    var privateVal = "Private Val";
    this.publicVal = "Public Val";

    var privateAlert = function (str) {
      alert(str + this.publicVal);
      alert(str + privateVal);
    }

    this.Run = function () //see here
    {
      privateAlert("Private Call: ");

      this.publicAlert = privateAlert;
      this.publicAlert("Public Call: ");

      privateAlert = this.publicAlert;
      privateAlert("Private Call: ");
      this.publicAlert("Public Call: ");
    }
  }

  var bar = new foo();
  bar.Run();

当创建新对象时,run()成为对象的私有方法,或者方法只属于var bar。该方法不能从其中执行privateAlert()函数,因为函数它的范围只能从已声明的函数中执行,但不能从现在属于某个其他对象的方法执行。澄清这个问题。

3 个答案:

答案 0 :(得分:3)

重要的是功能实例化的地方。在这种情况下,“Run”在“foo”构造函数中实例化,在该上下文中,private方法肯定是可见的。换句话说,它成为围绕“运行”功能的闭包的一部分。

可以这样想:“运行”功能的代码出现在“foo”构造函数中。 “Run”中的代码可以“看到”“foo”中的所有局部变量,如果“foo”在另一个函数内,它也可以看到所有这些变量。因为定义仅在调用“foo”时生效,所以所有这些局部变量始终可以在“运行”中的代码中随时被调用。这就是“封闭”一词的意思。

JavaScript中的范围和可见性与使用Java或C ++或C#等类的更多静态语言的工作方式有很大不同。在这些语言中,您显式构造对象,然后通过这些对象引用开始调用函数。在JavaScript中,闭包类似于自动动态对象,这些对象隐式地包含在从函数调用中“转义”的函数中。你无法直接访问这些对象,但它们仍然是真实的。

答案 1 :(得分:0)

范围与名称系统有关,并且没有提及访问权限。例如,在Java中,有三个关键字称为访问修饰符publicprivateprotected。 Javascript没有定义任何访问修饰符,因此所有名称都是公共的。

让我们这样说:要从文件系统中读取文件,您需要做两件事:

  1. 首先是文件名。当您请求操作系统为您提供文件指针时,它首先检查文件名称是否存在,可能是在从相对文件名和当前目录构造绝对路径名后,然后仅如果文件存在
  2. 检查您是否有权从中读取,最后为流提供处理程序。
  3. Javascript 范围是确定名称在当前上下文中是否意味着某事的规则。如果名称有意义,您可以随时访问它,因为Javascript不定义非公共修饰符。

    在您的情况下,您请求访问bar.Run。 Javascript解释器,使用当前上下文(我们假设是全局对象)向“javascript文件系统”询问“被称为”.bar.Run的对象(第一个点是有意的并且表示根)。一旦找到名称,就意味着它存在,并且您将始终能够访问它(在这种情况下调用该函数)。顺便说一句,没有像 javascript文件系统这样的东西,只是为了传达这个想法而没有技术术语和使用直观的类比。

    同样,检查范围规则以解析整个代码中的名称。在this.Run内,名称privateAlert可以已解决,这是唯一重要的规则:全局可以看到bar,全局可以访问bar.Run并且分配给它的函数可以访问privateAlert。这是链

答案 2 :(得分:0)

我猜Raffaele已经回答了你的大部分问题。但是,为了您的方便,让我尝试以不同的方式表达它并添加一些代码供您遵循。

我认为,您可以在这里学到两件事来理解为什么您的代码的行为方式。

  1. JavaScript具有this的后期绑定。只有当您调用方法时,运行时才会决定“on”它将被调用的对象。默认值是全局对象(例如,浏览器中的window,node.js中的global等)。要获得另一个this而不是全局的this.publicAlert = privateAlert;,您需要将该函数指定为所需对象的属性,就像通过privateAlert()所做的那样。之后,如果您直接致电this(在全局this.publicAlert()上)或通过public在本地调用它,即使它是相同的功能,也会有所不同。

  2. 正如其他答案中已经指出的那样。 Javascript没有privateprivateVal等等。您需要使用智能范围来“模拟”私有变量。在您的示例中,privateAlert在某种意义上是私有的,没有人可以从外部读取或写入它。 Foo也是如此。只有构造函数run中的via语句和console.log方法才能访问它们。

  3. 我扩充了您的示例以向您展示正在发生的事情(ps:使用alert通常比function Foo() { var privateVal = "Private Val"; var that = this; this.publicVal = "Public Val"; var privateAlert = function (str) { console.log("---" + str + "---") console.log("isLocalThis? ", this == that) console.log("isGlobalThis?", this == globalThis) console.log("private: ", privateVal) console.log("public: ", this.publicVal || "publicVal not available on 'this'") } this.run = function () { console.log("scope of run:", that, bar, privateAlert) console.log("isLocalThis? ", this == that) console.log("isGlobalThis?", this == globalThis) privateAlert("Private Call: "); this.publicAlert = privateAlert; this.publicAlert("Public Call: "); privateAlert = this.publicAlert; privateAlert("Private Call: "); this.publicAlert("Public Call: "); } } var bar = new Foo(); bar.run(); 更明智):

    console

    顺便说一下:alertthis是全局window的属性(即{{1}})。