16

example:

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

foo = new Foo();

original question:

I know that bla will be assigned to every instance of Foo. What will happen with blabla?

new question:

what I understand now:

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.

[Question:] Did i understand correctly?

Alwaysblue
  • 9,948
  • 38
  • 121
  • 210
Daniel
  • 1,562
  • 3
  • 22
  • 34
  • 1
    Your edited example is correct -- EXCEPT that `blabla` is UNIQUE to EVERY INSTANCE of `Foo`. So if `Foo` looked like `function Foo (number) { var blabla = number; this.bla = 37; this.getBlaBla = function () { return blabla; }; }` then `myFoo = new Foo(32);` and `yourFoo = new Foo(47);` would have completely different values for `.getBlaBla()`. `myFoo.getBlaBla() === 32; yourFoo.getBlaBla() === 47;` It's important to remember that even though it's a `locally-scoped value` that it's unique to each instance, and isn't going to be the same value for any Foo to read/write in a shared way. – Norguard Aug 16 '12 at 13:48

7 Answers7

11

Any internal-methods you give to this -- ie: this.method = function () {}; while inside of your Foo constructor function, are all going to have a reference to the blahblah which is unique to each instance of a Foo object.

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

But it's completely protected from access outside of wallet, unless you return it to somebody, from a privileged function.

wallet.balance; // undefined;

(added bit of interest -- if balance is a string, a number, or a boolean, even if you return it, that won't give people editing rights, or even permanent viewing access -- scalar variables are passed by value, so you're just passing the value of balance at the time -- if, however, balance was an object, a function or an array, they'd have permanent access to modify the crap out of your internal workings)

Note: methods HAVE to be assigned inside of the constructor for this to work. Prototypes can't access internal variables. Adding methods later won't give them access to internal variables.

This means that each instance will take up a little more memory, because each has its own copy of the methods, and has its own copy of the vars. But if what you're doing requires private data, this would be a good way to get it.

pinaa
  • 5
  • 2
Norguard
  • 26,167
  • 5
  • 41
  • 49
  • thanks. so if i make anoter instance "var myOtherWallet = new Wallet(); then it will make another closure in the memory which includes another "var balance = 0" ? – Daniel Aug 14 '12 at 17:21
  • @user1598423: Yes, each time you run the constructor it will create a new local variable, and when you associate methods with the object like that, each object will have its own instances of methods, with their own closures. – Guffa Aug 14 '12 at 17:38
  • @Norguard & @Daniel even we can make array and objects private along with scaler variables by using spread operator eg. `var balance =[1,2,3]; this.checkBalance = function () { return [...balance]; };//{...obj}` – ashwath hegde Jun 11 '20 at 08:27
6

In your example blabla is a local variable, so it will go away when the constructor function ends.

If you declare a function inside the constructor, which uses the variable, then the variable will be part of the closure for that function, and survives as long as the function (i.e. normally as long as the object):

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

  this.getBlabla = function() {
    alert(blabla); // still here
  }
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 1
    You probably mean that the variable survives as long as the *function*, or the *function object* so as to distinguish it from the constructed object. –  Aug 14 '12 at 15:34
  • so only variables that use "this" inside a contractor will become an attributes of the instances ? "var blabla = 10" will be only a local attribute of Foo - that will still exist only if there's a "this" method which uses it ? – Daniel Aug 14 '12 at 16:38
  • @user1598423: When you use `this.name =` you add a property to the object, just as you can do `obj.name =` from outside the object. A local variable in the constructor is not associated to the object at all, only indirectly if it's used by a method in the object. – Guffa Aug 14 '12 at 17:36
3

It will become a local (think of 'private') variable within Foo(). Meaning that you can't access it outside of 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
}

You could expose it (by returning it) with a Foo method.

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

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

Now outside of Foo():

var FooBar = new Foo();

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

jsFiddle demonstration

Mark Pieszak - Trilon.io
  • 61,391
  • 14
  • 82
  • 96
2

Variables declared with var inside a function used as a constructor will, like all other variables declared with var inside any function, be visible only during the execution of that function (unless the value is closed over using closures).

In other words, blabla is effectively invisible outside the function:

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

By defining functions which close over these variables, they become the closest thing JavaScript has to "private" variables:

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!
Platinum Azure
  • 45,269
  • 12
  • 110
  • 134
1

That variable is local to the constructor and won't be accessible outside of that scope (be it through this or otherwise), unless it is captured by a closure.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
0

If you don't use the var keyword, "blabla" becomes a global variable. At other points in the code if you also use blabla without var, it will also be global, and you can accidentally change other instances of blabla and introduce unintended bugs in your code. "var" puts the variable in the current scope, so in the case above, it's only accessible to Foo.

Kevin Nelson
  • 7,613
  • 4
  • 31
  • 42
-2

blabla can almost be considered a private member of Foo.

See this article from Douglas Crockford.

David Hoerster
  • 28,421
  • 8
  • 67
  • 102