[英]Javascript variable scope for objects created within function
考虑一下这段代码,
var getPerson = function() {
var _name = "";
var person = {};
person.getName = function() {
return _name;
}
person.setName = function(value) {
_name = value;
}
return person;
}
p1 = getPerson();
p1.setName("foo");
p2 = getPerson();
p2.setName("bar");
console.log(p1.getName()); // logs "foo"
console.log(p2.getName()); // logs "bar"
有人可以在这里解释_name的范围吗? p1._name和p2._name不存在。 该变量真正存储在哪里?
_name
的作用域为getPerson
函数,因为在此使用var
关键字对其进行了声明。
被嵌套在任何功能getPerson
将继承在声明的变量getPerson
,他们可以覆盖此声明自己的变量。 这个概念称为closure
,在进行JavaScript认真开发之前值得理解。
在JavaScript中,作用域不是由块决定的(与Java中一样),而是函数 scoped 。
所以, _name
中setName
功能是一样的_name
是在宣布getPerson
。
_name
的范围是getPerson()
函数中的任何代码。
在Javascript中,函数中的局部变量的作用范围是该函数的特定调用,并且每次调用该函数都会创建一组新的局部变量。 同样,这些局部变量也像其他变量一样被垃圾回收。 它们并不严格存储在函数退出时会被破坏的堆栈中。
由于进行了垃圾回收,只要仍然可以访问的代码引用了该变量,函数中的变量将继续存在。 因此,在您的getPerson()
函数中, _name
变量的范围是对getPerson()
函数的特定调用,但是该变量的生存期只要某些代码仍然可以到达该变量,即使在调用之后很长时间也是如此。 getPerson()
已完成。
这在Javascript中称为闭包,是一种非常有价值和有用的工具。
因为person.getName()
和person.setName()
甚至在getPerson()
函数完成执行后很长时间仍具有对_name
变量的引用,所以它将保持活动状态,并且不会被语言垃圾收集。
因此, scope
由变量的声明确定。 _name
的作用域范围是在其声明的函数中,并且该函数中还存在任何其他子作用域。 Javascript具有lexical
范围(这意味着范围由声明它的位置/方式决定)。 但是,范围内的变量的生存期由垃圾收集器单独确定,并且范围内的变量的生存期可以远远超出创建范围的函数的执行范围,只要其他一些可访问的代码仍然引用了该变量。
我喜欢将功能范围本身视为Javascript中的垃圾收集实体。 尽管Javascript的某些实现甚至可能比整个作用域更为精细(例如,尽可能在范围内进行垃圾收集),但垃圾收集而不是基于堆栈的作用域概念为您提供了一个框架,使您可以理解像Javascript这样的语言和像C ++这样的语言,它们使用显式堆栈框架来确定局部变量的寿命。
我认为您可能是从Java背景开始使用JavaScript的。
var _name = "";
在匿名函数(分配给getPerson
的函数)的范围内定义_name
变量。 该变量没有附加到任何对象,而只是一个普通变量。
如果您确实要执行p1._name和p2._name,则可以执行一种或两种解决方法。
var getPerson = function() {
var person = {
_name: ''
};
person.getName = function() {
return this._name;
}
person.setName = function(value) {
this._name = value;
}
return person;
}
p1 = getPerson();
p1.setName("foo");
p2 = getPerson();
p2.setName("bar");
console.log(p1.getName()); // logs "foo"
console.log(p2.getName()); // logs "bar"
console.log(p1._name); // logs "foo"
console.log(p2._name); // logs "bar"
var getPerson = function() {
var _name = "";
var person = {
get _name () {
return _name;
}
};
person.getName = function() {
return _name;
}
person.setName = function(value) {
_name = value;
}
return person;
}
p1 = getPerson();
p1.setName("foo");
p2 = getPerson();
p2.setName("bar");
console.log(p1.getName()); // logs "foo"
console.log(p2.getName()); // logs "bar"
console.log(p1._name); // logs "foo"
console.log(p2._name); // logs "bar"
还有许多其他方法可以完成此操作; JavaScript是一种动态语言。
您在上方所拥有的被称为闭包。 通过返回person
,您将暴露方法person.getName
和person.setName
。 由于这些方法是在getPerson
中定义的,因此它们也可以访问_name
变量(因为_name
是在同一函数中定义的)。
getPerson
外部的代码无法访问_name
,但是可以(通过受控方式)通过getName和setName方法访问_name
。 这将为_name
变量创建隐私。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.