0

It is my first question here, so apologise if I missed anything. Perhaps solution for my problem could be find, but I have no idea how to search for it, no clues about how to ask it in google or something.

I have a following problem, let's have such constructor

const Product = function (color) {
    let self = {};

self.setColor = function(colorToSet) {
  color = colorToSet;
}

self.getColor = function() {
  return color;
}

return self;
};

now when I tried to use:

let self = {}, color;

in chrome console I received error that color has been already declared, so I removed color field and after this (with a snippet code above), magic happened that I cannot explain.

let's say I will write something like this:

let a = Product("Yello");
a.getColor() ----> "Yellow"
a.setColor("red");
a.getColor() ----> "red";

If it returns color for the first time, then it has to be declared somehow. I do not know where is color field, I cannot find it in the object nor in its prototype, nowhere actually. Could you explain me why ? and where it is ?

I know that I can just declare color for example: self.color = color; But I want to know how is working the example above and what happened with color field.

Also could you tell me if I can use let with declaring values from parameters in such way ?

const Product = function (color) {
let self = {}, color;

self.setColor = function(colorToSet) {
  color = colorToSet;
}

self.getColor = function() {
  return color;
}

return self;
};
Velemir
  • 143
  • 1
  • 9
  • Afaik, if you use just `color`, it gets appended to the `window` Object. You're actually getting/setting `window.color`. –  Jan 26 '17 at 13:51
  • @Chris G: color is not being defined on `window`, this is **closure** behaviour – Pineda Jan 26 '17 at 14:19

2 Answers2

0

It's not magic :) this behaviour happens because:

You're returning an object that has two methods which are closures.

When a function is defined within another function and then a reference to it stored somewhere (in this case when you returned then attached to the self variable) then a closure is created.

In short, a function has access to variables created inside its definition block and to its enclosing environment (your constructor definition).

As a result it will have access to any variables in the enclosing scope at the time the parent was invoked.

This includes any parameters of that enclosing Product function, i.e. the color argument you define.

So:

  • You invoke Product passing in a colour and store this in a variable a. At this point a will contain a reference to an object whose properties include two methods getColor and setColor

  • since the latter methods are closures, they have access to their enclosing scope at the time Product (their enclosing function environment was called). Since Product was invoked with a color, a variable called color local to Product but also available to any closures will be created and assigned the value passed in. In this case color will be equal to 'Yellow

  • Since both methods were defined in the same scope at the same time, they both have access to this variable, producing the results you experienced.

Community
  • 1
  • 1
Pineda
  • 7,435
  • 3
  • 30
  • 45
0

It has to be declared somehow. I do not know where is color field, I cannot find it in the object nor in its prototype, nowhere actually. Could you explain me why? and where it is?

It is the variable that you declared by using it as a parameter name. That parameter variable is scoped to the Product function, i.e. can be used anywhere inside it. It's the reason why you get an "already declared" error if you try to use let color.

Your methods can access (read/write) this local variable because they are closures.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375