如果函数有范围,它们应该在该范围内执行,但在这里我认为它不同。查看代码
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()函数,因为函数它的范围只能从已声明的函数中执行,但不能从现在属于某个其他对象的方法执行。澄清这个问题。
答案 0 :(得分:3)
重要的是功能实例化的地方。在这种情况下,“Run”在“foo”构造函数中实例化,在该上下文中,private方法肯定是可见的。换句话说,它成为围绕“运行”功能的闭包的一部分。
可以这样想:“运行”功能的代码出现在“foo”构造函数中。 “Run”中的代码可以“看到”“foo”中的所有局部变量,如果“foo”在另一个函数内,它也可以看到所有这些变量。因为定义仅在调用“foo”时生效,所以所有这些局部变量始终可以在“运行”中的代码中随时被调用。这就是“封闭”一词的意思。
JavaScript中的范围和可见性与使用Java或C ++或C#等类的更多静态语言的工作方式有很大不同。在这些语言中,您显式构造对象,然后通过这些对象引用开始调用函数。在JavaScript中,闭包类似于自动动态对象,这些对象隐式地包含在从函数调用中“转义”的函数中。你无法直接访问这些对象,但它们仍然是真实的。
答案 1 :(得分:0)
范围与名称系统有关,并且没有提及访问权限。例如,在Java中,有三个关键字称为访问修饰符:public
,private
和protected
。 Javascript没有定义任何访问修饰符,因此所有名称都是公共的。
让我们这样说:要从文件系统中读取文件,您需要做两件事:
Javascript 范围是确定名称在当前上下文中是否意味着某事的规则。如果名称有意义,您可以随时访问它,因为Javascript不定义非公共修饰符。
在您的情况下,您请求访问bar.Run
。 Javascript解释器,使用当前上下文(我们假设是全局对象)向“javascript文件系统”询问“被称为”.bar.Run
的对象(第一个点是有意的并且表示根)。一旦找到名称,就意味着它存在,并且您将始终能够访问它(在这种情况下调用该函数)。顺便说一句,没有像 javascript文件系统这样的东西,只是为了传达这个想法而没有技术术语和使用直观的类比。
同样,检查范围规则以解析整个代码中的名称。在this.Run
内,名称privateAlert
可以已解决,这是唯一重要的规则:全局可以看到bar
,全局可以访问bar.Run
并且分配给它的函数可以访问privateAlert
。这是链
答案 2 :(得分:0)
我猜Raffaele已经回答了你的大部分问题。但是,为了您的方便,让我尝试以不同的方式表达它并添加一些代码供您遵循。
我认为,您可以在这里学到两件事来理解为什么您的代码的行为方式。
JavaScript具有this
的后期绑定。只有当您调用方法时,运行时才会决定“on”它将被调用的对象。默认值是全局对象(例如,浏览器中的window
,node.js中的global
等)。要获得另一个this
而不是全局的this.publicAlert = privateAlert;
,您需要将该函数指定为所需对象的属性,就像通过privateAlert()
所做的那样。之后,如果您直接致电this
(在全局this.publicAlert()
上)或通过public
在本地调用它,即使它是相同的功能,也会有所不同。
正如其他答案中已经指出的那样。 Javascript没有private
,privateVal
等等。您需要使用智能范围来“模拟”私有变量。在您的示例中,privateAlert
在某种意义上是私有的,没有人可以从外部读取或写入它。 Foo
也是如此。只有构造函数run
中的via语句和console.log
方法才能访问它们。
我扩充了您的示例以向您展示正在发生的事情(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
顺便说一下:alert
和this
是全局window
的属性(即{{1}})。