Purpose of multiple assignment var x = this.x = function(){}? - javascript

In Mootools the following pattern occurs frequently:
var x = this.x = function(){}
For example:
var typeOf = this.typeOf = function(item){ ...
I understand multiple assignment results in function being assigned to both x and this.x. But I thought in the global scope x is implicitly this.x, so it seems redundant. Is this an optimization technique, or is there some other purpose to this pattern?

This is only redundant if this code isn't executed in a function.
If it's in a function, the var is local, even if the context (this) is the global one.
Look at this :
function a() {
var x = 1;
console.log(x)
}
function b() {
console.log(x); // fails
}
a();
b();
If you want to be both able to use x directly in a and have this.x in b, then you need the double assignation :
var x = this.x = 1;
I frequently use this pattern in big functions when I have a variable I use a lot and for which I prefer a direct access without this..

var x is not equals this.x, var x is a varible private of a js class and this.x is a public propertie, so the code create 2 ways for invoke a function
Here an example:
function exampleA() {
this.x = 1;
var x = 2;
this.show = function () {
alert("A.x:" + x);
alert("A.this.x:" + this.x);
};
}
function exampleB() {
var x = this.x = 1;
this.x +=1;
this.show = function () {
alert("B.x:" + x);
alert("B.this.x:" + this.x);
};
}
$(document).ready(
function () {
var example1 = new exampleA();
example1.show();
var example1 = new exampleB();
example1.show();
});

Related

Return function not using variables

Basically, I want to organize my code better by creating function definitions wherever I can. When I try to create a new function outside the current scope and return that, it will say x and y are not defined.
I know it's definitely something to do with scoping. Is there anything I can do to organize my code like in the 2nd code paragraph below? Or do I have to declare my functions in the right scope.
# Works
function RandomFunction() {
x = 1;
y = 1;
marker.addEventListener('click', function(x, y) {
return function() {
console.log(x+y);
}
}
}
# Not working
function RandomFunction() {
x = 1;
y = 1;
marker.addEventListener('click', function(x, y) {
return add;
}
}
function add() {
console.log(x+y);
}
The function add needs to have each number passed in as parameters(firstNum, secondNum).
The function RandomFunction can declare x and y as variables above the event listener scope. Then when the click event is activated, x and y from the RandomFunction scope will be passed to the add function where the add function can reference those values as firstNum and secondNum.
Also, there is no need to return the function "add" within the click event's callback function.
function RandomFunction() {
var x = 1;
var y = 1;
marker.addEventListener('click', function() {
add(x, y);
});
}
function add(firstNum, secondNum) {
console.log(firstNum + secondNum);
}
RandomFunction();
I am not sure what you want to accomplish, but if you want to return a function that "sees" your x,y and can operate on them here it is :
function RandomFunction() {
var x = 1;
var y = 1;
marker.addEventListener('click', function() {
// (add(x, y))(); this will give you 2 in console
return add(x, y); // this will return a function that when you execute it will give 2 as result
})
}
function add(x, y) {
return function() {
console.log(x + y);
}
}
RandomFunction();
I am not sure what you want to do, but this will return a function that has access to your x,y when marker is clicked.

Object function scope

factory(n) returns objects with functions.
func1 function definition creates its own scope, and x inside this function references x = n + ''.
But func2 is a reference and the scope is wrong.
Is there a way to return an object from create so its functions were references (not separate definitions)?
Actually, I'm fine with func1 approach while function definition footprint is small. If it is a complex function it would be better not to clone this function into every object comming from factory(n). inner_func may not use this, it is simple function. Also I want to avoid new and this.
var factory = (function(){
var x = '!';
return function create(n){
var x = n + '';
return {
func1: function(y){return inner_func(x, y); },
/* vs */
func2: inner_func_api
}
}
function inner_func_api(y){ return inner_func(x, y); }
function inner_func(a, b){ return a + b; }
}());
var f1 = factory(2);
var f2 = factory(3);
var f1_func1 = f1.func1(4);
var f2_func1 = f2.func1(5);
var f1_func2 = f1.func2(4);
var f2_func2 = f2.func2(5);
console.log(f1_func1, f2_func1); //24 35
console.log(f1_func2, f2_func2); //!4 !5
You could define that function separately from the object initializer on the return statement:
var factory = (function(){
var x = '!';
return function create(n){
var x = n + '';
function func1(y) {
return inner_func(x, y);
}
return {
func1: func1,
/* vs */
func2: inner_func_api
}
}
function inner_func_api(y){ return inner_func(x, y); }
function inner_func(a, b){ return a + b; }
}());
However, it makes no practical difference, and it doesn't matter how big or complicated that function is. Function instances do take up space, but the code for the function is constant (immutable) and doesn't need to be part of every Function object created from the same piece of source code.

How to define a javascript internal method that needs to be accessible from inside obj and out

I'm trying to fully grasp JavaScript inheritance and encapsulation. Take the following example (and here is a fiddle of it):
myPage = {
someObj: function() {
var x = 0;
//PRIVATE: increment by 10
var inc10 = function() {
x = x+10;
};
//PUBLIC: increment
this.inc = function() {
x = x+1;
};
//PUBLIC: decrement
this.dec = function() {
x = x-1;
};
//PUBLIC: output the current value of x
this.getValue = function() {
return x;
}
inc10(); //as soon as obj1 is created lets add 10
this.inc(); //as soon as obj1 is created lets add 1 more
}
};
obj1 = new myPage.someObj(); //x starts out at 11
// obj1.inc10(); won't work because it's private, excellent
obj1.dec();
obj1.inc();
alert(obj1.getValue());
My question is about the inc() method. I need it to be callable from inside and outside of the object. Is this the proper way to do that?
I need it to be callable from inside and outside of the object. Is this the proper way to do that?
Your script does seem to work as expected already, you are calling the method as this.inc() in your constructor perfectly fine - not sure why it needs improvement.
You could however define it as a local function, which you then are going to export as a method - and have it still available "inside" as a local variable:
function SomeObj() {
// local declarations:
var x;
function inc10() {
x = x+10;
}
function inc1() {
x = x+1;
}
// exported as property:
this.inc = inc1; // <== the function from above, not a literal
this.dec = function() {
x = x-1;
};
this.getValue = function() {
return x;
};
// initialisation:
x = 0;
inc10();
inc1(); // this.inc() would still work
}
To call function from inside and outside without attaching it to an obj.
This should work ...
myPage = function() {
var x = 0;
//PRIVATE: increment by 10
var inc10 = function() {
x = x+10;
};
//PUBLIC: increment
this.inc = function() {
x = x+1;
};
//PUBLIC: decrement
this.dec = function() {
x = x-1;
};
//PUBLIC: output the current value of x
this.getValue = function() {
return x;
}
inc10(); //as soon as obj1 is created lets add 10
this.inc(); //as soon as obj1 is created lets add 1 more
};
obj1 = new myPage; //x starts out at 11
// obj1.inc10(); won't work because it's private, excellent
obj1.inc();
alert(obj1.getValue());

accessing an inner variable in a javascript object

Consider this errorful code:
x = {
y : "why",
z : function() {
return y + " zed";
}
}
The function z does not work: "ReferenceError: y is not defined".
Is there a way to access y from within the function z without fully specifying it as x.y?
I could of course rewrite this as
x = function() {
var self = this;
this.y = "why";
this.z = function() {
return self.y + " zed";
};
return this;
}();
... but gosh.
Simply use this if you call the function with x.z():
var x = {
y : "why",
z : function() {
return this.y + " zed";
}
};
DEMO: http://jsfiddle.net/hZxVu/
No, you will need to rewrite it as such. y is a property of that object, and you can't access it without the object - unlike accessing a variable (e.g. self in your rewrite) from a closure.
Of course, when you invoke the function as x.z(), the this keyword will point to the object too, so that you can write it as
return this.y + " zed";
as long as you always call the function in context of that object.
#VisioN has the straight-forward answer. It might help to visualize why this is necessary if you rewrite your code as such:
var x = {};
x.y = "why";
x.z = function() {return this.y + " zed"; };
alert(x.z());
Here y and z are properties of an object, but there is no functional closure scoping. You need the "this" keyword to access a property of the parent object.
Alternatively,
var x = function () {
var y = "why";
var z = function () { return y + " zed?"; };
return z();
};
alert(x());
This demonstrates functional scoping by accessing y without using this. Inside of x, y is known. Outside, it is not.
Using the revealing module pattern:
var x = (function () {
y = "why";
z = function() {
return y + " zed";
};
return {
"y": y,
"z": z
};
})();
//now you can call:
x.y // "why"
x.z() // "why zed"

Triggering Instance methods by firing the Parent method

What is the best way to fire a method in many children by calling the parent's method?
For example, lets say I have a parent object Foo which has many instances: BarX, BarY, etc.
Foo = function(){
x = null;
y = null;
move = function(){
x += 1;
y += 1;
};
}
BarX = new Foo();
BarX.x = 50;
BarX.y = 50;
BarY = new Foo();
BarY.x = 200;
BarY.y = 200;
Is there any easy way to fire off the move function in all instances? Am I limited to looping through the instances and firing off the function like that or can I somehow fire the function in Foo and have it trickle down and fire off all instances who extend Foo?
No. But you could be more clever about it. Make a static moveAll function on Foo. Examples make things clearer. Here is the fiddle.
var Foo = function(x, y){
this.x = x;
this.y = y;
this.move = function(){
x += 1;
y += 1;
alert(x + ' ' + ' ' + y);
};
Foo.instances.push(this); // add the instance to Foo collection on init
};
Foo.instances = [];
Foo.moveAll = function(){
for(var i = 0; i < Foo.instances.length; i++)
Foo.instances[i].move();
}
var a = new Foo(5, 6);
var b = new Foo(3, 4);
Foo.moveAll();

Categories