javascript closures and prototypes - javascript

I thought I have understood the idee of closures, but the following code
behaves surprisingly for me:
function A(x)
{
this.getX1 = function () { return x; }
A.prototype.getX2 = function () { return x; }
}
var a1 = new A(1);
var a2 = new A(2);
console.log ('a1.getX1()=%d', a1.getX1 ()); // 1
console.log ('a2.getX1()=%d', a2.getX1 ()); // 2
console.log ('a1.getX2()=%d', a1.getX2 ()); // 2 ???
console.log ('a2.getX2()=%d', a2.getX2 ()); // 2
I could understand if prototype methods behave differently from
instance methods, but this looks like x has become a static variable.
Changing the order of calls does not change results.

When you change the prototype you're changing the function for all instances of the given class, including those that already exist.
Therefore when you call...
A.prototype.getX2 = function () { return x; }
You're setting that for the existing a1 instance of A. So effectively you're ending up with the following pseudo code:
<all instances of A>.getX2 = function () {
return <latest value of x passed to A constructor>;
}

The static member here is A.prototype.getX2. The second call to A.prototype.getX2 = function () { return x; } (due to var a2 = new A(2);) replaces the first one. To understand it you can reverse the order of instantiations:
var a2 = new A(2);
var a1 = new A(1);
Then you'll have:
a1.getX1()=1
a2.getX1()=2
a1.getX2()=1
a2.getX2()=1

You're defining getX2 twice, each time you create a new A. The result for that function will always be the last X. Considering rewriting your code like this:
function A(x) {
this.x = x;
this.getX1 = function() {
return this.x;
}
}
A.prototype.getX2 = function() {
return this.x;
}
var a1 = new A(1);
var a2 = new A(2);
console.log('a1.getX1()=%d', a1.getX1()); // 1
console.log('a2.getX1()=%d', a2.getX1()); // 2
console.log('a1.getX2()=%d', a1.getX2()); // 1
console.log('a2.getX2()=%d', a2.getX2()); // 2​​​
This way, you only define getX2 once and it works as expected.

You have written
function A(x)
{
this.getX1 = function () { return x; }
A.prototype.getX2 = function () { return x; }
}
This constructor overwrites A.prototype.getX2 each time.
So first
var a1 = new A(1); // This invokes A and adds a function `getX2` to the prototype of `A`which returns `x` that is `1`
var a2 = new A(2); // This invokes A and overwrites the function `getX2` in the prototype of `A` with a function which returns `x` that is `2` now.
So it should be like this
function A(x)
{
this.getX1 = function () { return x; }
}
A.prototype.getX2 = function () { return this.getX1(); }

Related

In JavaScript, is there a way to get closure parameters

I have two file:
//------------a.js--------------
function a(){
return '1'
}
var testCase = {
func(){
return a()
}
}
module.exports = testCase
//------------b.js--------------
var testCase = require('./a.js')
//Can I get closure parameters(function a) that not modify a.js?
Is there a way to get closure parameters In JavaScript? Thank You!
If you mean to return the list of parameters from a closure like get x and y from closure run(x, y) {} which is inside function walk() {} then the below code might help.
function walk() {
function run(x, y) {
return x + y;
}
return run;
}
var fun = walk();
fun.getParameters = function () {
var functionText = this.prototype.constructor.toString();
return functionText
.substring(functionText.indexOf('(') + 1, functionText.indexOf(')'))
.split(',')
.map(x => x.trim());
};
console.log(fun.getParameters());

javascript, can a variable be a value and also a function?

It is possible to code in javascript like the following:
var foo = function(n) { //magic codes };
var bar = foo(2);
bar + 2 // result: 4
bar(2) // result: 4
bar(2)(2) // result: 6
A variable can only hold one value. That value can be a function.
An object can have a toString() method which could be hacked to get close to what you are trying to do.
function myFactory(value) {
function myFunction(add) {
return myFactory(value + add);
}
myFunction.toString = function() {
return value;
};
return myFunction;
}
var bar = myFactory(2);
console.log(bar + 2);
console.log(bar(2));
console.log(bar(2)(2));
This is, of course, horrible.
Currying can be done in Javascript, by returning a function.
By default variables can either be values (literal, or results of functions), or function declarations.
function add(number) {
return function(number2) {
return number + number2;
}
}
console.log(add(5)(6));
There are ways to achieve what you described bar + 2, but that's unconventional, and in my opinion, you shouldn't use them in Javascript.
I got inspired by Quetin's answer and found the valueOf property
var foo = function(n) {
var fn = function(x) {
return foo(n + x);
};
fn.valueOf = function() {
return n;
};
return fn;
}
var bar = foo(2);
console.log(bar + 2 === 4, bar);
console.log(bar(2) === 4, bar(2));
console.log(bar(2)(2) === 6, bar(2)(2));
I admit the log results does come out strange but it works as intended.

How can I add namespace to revealing prototype pattern

I have this code,
var MyNamespace = MyNamespace || {};
MyNamespace.Calculator = function (eq) {
//state goes here
this.eqCtl = document.getElementById(eq);
};
MyNamespace.Calculator.prototype = function () {
//private members
var add = function (x, y) {
this.eqCtl.innerHTML = x + y;
},
subtract = function (x, y) {
this.eqCtl.innerHTML = x - y;
};
//public members
return {
add: add,
subtract: subtract
};
} ();
Var calc = new MyNamespace.Calculator('eqCtl');
calc.add(2,2);
Questions
Why am I getting exception after adding "MyNamespace" to it ? It works if I remove it...
It's recommended not to use "new" keyword for creating objects by Douglas Crockford Then how can I overcome this solution.
Fiddle: https://jsfiddle.net/bpo50qjg/
You have a typo in:
Var calc = new MyNamespace.Calculator('eqCtl');
It should be:
var calc = ...

How does implicit passing of object reference work?

I have some Javascript code which works fine so far but I do not understand the how the variable "me" is set in the function "run"?
GameLoop.prototype.run = function() {
this.startTime = new Date().getTime();
var currentTimeMillis = this.startTime;
var loops;
var interpolation=0.0;
this.running=true;
return function(me){
loops = 0;
while (new Date().getTime() > currentTimeMillis && loops < me.MAX_FRAMESKIP) {
me.updateGame();
currentTimeMillis += me.SKIP_TICKS;
loops++;
}
interpolation = parseFloat(new Date().getTime() + me.SKIP_TICKS - currentTimeMillis) / parseFloat(me.SKIP_TICKS);
me.drawGame(interpolation);
}
}
The function is called continuously by the browser's animate function below. Since I do not pass any reference to the call f.run(), i guess the correct reference to me is set implicitly. Can someone explain me or give me some useful links which explains this behaviour?
GameLoop.prototype.recursiveAnim = function() {
var f = this.run();
f.run();
this.animFrame( this.recursiveAnim );
};
By calling run you get a function in return, that function has one parameter and its called me.
For example
var x = function () { return function (me) { return me; } }
// by calling x, you get the function: `function (me) { return me; }
var f = x();
console.log(f(1)); // answer is 1

Javascript function copies

I have a question about how javascript stores functions internally.
Given this code:
var makesomething = function (x) {
var thing = {
x: x
};
thing.do = function () {
this.x++;
};
return thing;
};
var x1 = makesomething(1);
var x2 = makesomething(2);
Since I called the makesomething function twice, does that mean that there are essentially two copies of the "do" function or do the objects have reference to the same function but get called with different closure?
There are two copies, one created each time you called makesomething().
You'll notice that x1.do === x2.do is false.
If instead you do this:
var doIt = function() {
this.x++;
};
var makesomething = function (x) {
var thing = {
x: x
};
thing.do = doIt;
return thing;
};
var x1 = makesomething(1);
var x2 = makesomething(2);
Then both refer to the same function, and x1.do === x2.do will be true.

Categories

Resources