JavaScript 构造函数中的“var”变量会发生啥?

Posted

技术标签:

【中文标题】JavaScript 构造函数中的“var”变量会发生啥?【英文标题】:What happens with "var" variables inside a JavaScript Constructor?JavaScript 构造函数中的“var”变量会发生什么? 【发布时间】:2012-08-10 22:27:32 【问题描述】:

示例:

function Foo() 
    this.bla = 1;
    var blabla = 10;
    blablabla = 100;
    this.getBlabla = function ()  
        return blabla; // exposes blabla outside
    


foo = new Foo();

原始问题:

我知道bla 将分配给 Foo 的每个实例。 blabla 会发生什么?

新问题:

我现在的理解:

this.bla = 1;     // will become an attribute of every instance of FOO.
var blabla = 10;  // will become a local variable of Foo(**not** an attribute of every    instance of FOO), which could be accessed by any instance of FOO only if there's a method like "this.getBlabla".
blablabla = 100;  // will define a **new** (or change if exist) global(window) variable.

[问题:]我理解正确吗?

【问题讨论】:

您编辑的示例是正确的——除了blablaFoo 的每个实例都是唯一的。因此,如果Foo 看起来像function Foo (number) var blabla = number; this.bla = 37; this.getBlaBla = function () return blabla; ; ,那么myFoo = new Foo(32);yourFoo = new Foo(47); 将具有完全不同的.getBlaBla() 值。 myFoo.getBlaBla() === 32; yourFoo.getBlaBla() === 47; 重要的是要记住,即使它是 locally-scoped value,它对于每个实例都是唯一的,并且对于任何 Foo 以共享方式读取/写入的值都不相同。 【参考方案1】:

您提供给 this 的任何内部方法 - 即:this.method = function () ; 在您的 Foo 构造函数内部,都是 将引用blahblah,这对于Foo 对象的每个实例都是唯一的。

function Wallet () 
    var balance = 0;
    this.checkBalance = function ()  return balance; ;
    this.depositAmount = function (amount)  balance += amount; ;



var wallet = new Wallet();
wallet.checkBalance();   // 0
wallet.depositAmount(3);
wallet.checkBalance();   // 3

但它完全受到保护,无法从钱包外部访问,除非你通过特权功能将其归还给某人。

wallet.balance; // undefined;

(增加了一点兴趣——如果balancestringnumberboolean,即使您将其退回,也不会授予人们编辑权限,甚至无法永久查看访问 -- 标量变量是按值传递的,所以你只是传递了 balance 的值当时 -- 但是,如果 balance 是 objectfunction 或 @ 987654333@,他们将拥有永久访问权限,可以修改您内部工作中的废话)

注意:方法 HAVE 必须在构造函数内部分配才能正常工作。 原型无法访问内部变量。 稍后添加方法不会让它们访问内部变量。

这意味着每个实例将占用更多内存,因为每个实例都有自己的方法副本,并且有自己的 var 副本。 但是,如果您正在做的事情需要私人数据,这将是获取它的好方法。

【讨论】:

谢谢。因此,如果我创建另一个实例“var myOtherWallet = new Wallet(); 那么它将在内存中创建另一个闭包,其中包括另一个“var balance = 0”? @user1598423: 是的,每次运行构造函数时,它都会创建一个新的局部变量,当您将方法与对象关联时,每个对象都会有自己的方法实例,以及它们的自己的闭包。 @Norguard & @Daniel 甚至我们可以通过使用扩展运算符将数组和对象以及缩放器变量设为私有,例如。 var balance =[1,2,3]; this.checkBalance = function () return [...balance]; ;//...obj【参考方案2】:

在你的例子中,blabla 是一个局部变量,所以它会在构造函数结束时消失。

如果你在构造函数中声明了一个使用变量的函数,那么变量将成为该函数闭包的一部分,并且与函数一样长(即通常与对象一样长):

function Foo() 
  this.bla = 1;
  var blabla = 10;

  this.getBlabla = function() 
    alert(blabla); // still here
  

【讨论】:

你可能的意思是,该变量只要函数函数对象存在,以便与构造对象区分开来。 所以只有在承包商内部使用“this”的变量才会成为实例的属性? "var blabla = 10" 将只是 Foo 的一个本地属性 - 只有当有一个使用它的 "this" 方法时它才会存在? @user1598423:当您使用this.name = 时,您可以向对象添加一个属性,就像您可以从对象外部执行obj.name = 一样。构造函数中的局部变量根本不与对象关联,只有在被对象中的方法使用时才会间接关联。【参考方案3】:

它将成为Foo() 内的本地(想想“私有”)变量。这意味着您无法在 Foo() 之外访问它。

function Foo() 
  this.bla = 1; // this becomes an extension of Foo()
  var blabla = 10; // this becomes a "Local" (sort of like a 'private') variable

您可以使用 Foo 方法公开它(通过返回它)。

function Foo() 
    var blabla = 10; // local

    this.getBlabla = function ()  
        return blabla; // exposes blabla outside
    

现在在 Foo() 之外:

var FooBar = new Foo();

var what_is_blabla = FooBar.getBlabla(); //what_is_blabla will be 10

jsFiddle demonstration

【讨论】:

这是一个本地变量。我会避免使用术语“私有”,因为它在谈论其他语言的可见性时使用(javascript 没有)。 您可以添加其他公开的函数可以访问blabla。所以通过添加this.method = function() return blabla; ;,可以检索到blabla的内容。 很好的电话费利克斯,忘了技术上没有任何“私人”。实际上只是添加了Sirko的东西! Foo.getBlabla(); 也不正确......应该是instanceOfFoo.getBlabla() 刚刚添加了它现在工作的构造函数。不知何故忽略了它!【参考方案4】:

如果不使用 var 关键字,“blabla”将成为全局变量。在代码中的其他点,如果您还使用不带 var 的 blabla,它也将是全局的,您可能会意外更改 blabla 的其他实例并在代码中引入意外错误。 "var" 将变量放在当前范围内,所以在上面的例子中,它只能被 Foo 访问。

【讨论】:

【参考方案5】:

blabla 几乎可以被认为是Foo 的私​​有成员。

请参阅 Douglas Crockford 的 this 文章。

【讨论】:

【参考方案6】:

在用作构造函数的函数中使用var 声明的变量将与在任何函数中使用var 声明的所有其他变量一样,仅在该函数执行期间可见(除非使用闭包关闭该值) .

换句话说,blabla 在函数之外实际上是不可见的:

var foo = new Foo();
console.log(foo.bla);     // 1
console.log(foo.blabla);  // throws NameError

通过定义关闭这些变量的函数,它们成为 JavaScript 最接近“私有”变量的东西:

function Foo() 
    this.bla = 1;
    var private = 1;

    this.increment = function() 
        ++private;
    

    this.getPrivateValue = function() 
        return private;
    


foo = new Foo();
console.log(foo.bla);                // 1
foo.bla = 6;                         // legal
console.log(foo.bla);                // 6
console.log(foo.getPrivateValue());  // 1
// console.log(foo.private);         // would throw an error
foo.increment();                     // legal
console.log(foo.getPrivateValue());  // 2
// foo.getPrivateValue() = 5;        // syntax error. Still can't reassign to private no matter what you try!

【讨论】:

【参考方案7】:

该变量是构造函数的本地变量,并且无法在该范围之外访问(通过this 或其他方式),除非它被闭包捕获。

【讨论】:

以上是关于JavaScript 构造函数中的“var”变量会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

javascript怎么定义函数

JavaScript 变量声明varletconst详解

js中的var是啥意思,

JavaScript使用构造函数获取变量的类型名

JavaScript使用构造函数获取变量的类型名

javascript 原型