accessing an inner variable in a javascript object - javascript

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"

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.

Variable hoisting examples [duplicate]

This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 7 years ago.
Hi I have a snippet of code. I am confused about change of value x1 when I remove non-related part of same code. I searched about it and I came to know that it has to do with hoisting. But the value x1 is still unclear even with hoisting concept for me. Can someone please make me clear on this?
var x = 10;
function main() {
document.write("<br>x1 is " + x);
x = 20;
if (x > 0) {
var x = 30;
document.write("<br>x2 is " + x);
}
var x = 40;
var f = function(x) {
document.write("<br>x3 is " + x);
}
f(50);
}
main();
The output of this code is:
x1 is undefined
x2 is 30
x3 is 50
If I change this code to:
var x = 10;
function main() {
document.write("<br>x1 is " + x);
}
main();
The output is:
x1 is 10
So what is happening here is a common pitfall.
The simplest way to put this is. When you set var x = 30 inside your main function, you are actually redefining the scope that var x = 10 had for use inside this function. This has to do with how Javascript executes and scope.
By defining x inside the function, your scope for x has changed. Below is an example of what I mean and a version of your code that works
Example:
var test = 'test';
function run(){
console.log(test);
var test=1;
}
Your Code Updated:
var x = 10;
function main() {
console.log("<br>x1 is " + x);
x = 20;
if (x > 0) {
x = 30;
console.log("<br>x2 is " + x);
}
x = 40;
var f = function(x) { console.log("<br>x3 is " + x); }
f(50);
}
main();
Good question btw.
Since this is somewhat of a very interesting scope of how Javascript executes, consider the following code and its outputs to get the full idea
var test = 'test';
function run(){
console.log(test);
test=1;
console.log(test);
var test=2;
console.log(test);
}
console.log(test);
run();
console.log(test);
Very interesting to see how this reacts.
All variable and function declarations get "hoisted" or moved to the top of their scope. The undefined value for x is caused because the var x statement gets moved up to the top of main however the assignment = 30 does not.
So, your code will read more like this:
var x = 10; // x is 10
function main() {
var x; // x declaration is "hoisted"
document.write("<br>x1 is" + x); // x1 is undefined
x = 20; // x is 20
if (x > 0) {
x = 30; // x is 30
document.write("<br>x2 is" + x);// x2 is 30
}
x = 40; // x is 40
var f = function(x) { // x is 50
document.write("<br>x3 is" + x);// x3 is 50
}
f(50);
}
main();
You can read more about Hoisting here: JavaScript Scoping and Hoisting

Why put a method on an object's prototype? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Understanding prototypal inheritance in JavaScript
(6 answers)
What’s the purpose of prototype? [duplicate]
(3 answers)
Closed 9 years ago.
What are the benefits of putting stuff on an object's prototype? For example, these two implementations of ChessPiece seem very similar. What are the trade-offs?
Without prototype
var ChessPiece = function(x, y) {
var self = this;
this.x = x;
this.y = y;
this.getNotation = function() {
return 'abcdefgh'[self.x] + '12345678'[self.y];
};
}
var pawn1 = new ChessPiece(1, 0);
pawn1.getNotation(); // 'b1';
With prototype
var ChessPiece = function(x, y) {
this.x = x;
this.y = y;
}
ChessPiece.prototype.getNotation = function() {
return 'abcdefgh'[this.x] + '12345678'[this.y];
}
var pawn2 = new ChessPiece(1, 1);
pawn2.getNotation(); // 'b2'
To me, the most significant difference is that when getNotation is on ChessPiece's prototype, that method is shared by all instances. When it's not on the prototype, there are multiple copies of getNotation. Does this matter? Is there more I am missing?
As an aside, the reason I prefer the first method is because it is cleaner to write everything in a single constructor function, rather than having to declare ChessPiece and then assign each method on separate lines. Is there a way to work around that issue, if the latter is preferred?
Your without prototype is similar in concept to what Douglas Crockford recommends in "JavaScript: The Good Parts" with an important exception. His version of your example might look something like this:
var chessPiece = function(x, y) {
var obj = {};
obj.x = x;
obj.y = y;
obj.getNotation = function() {
return 'abcdefgh'[obj.x] + '12345678'[obj.y];
};
return obj;
}
var pawn1 = chessPiece(1, 0);
pawn1.getNotation(); // 'b1';
pawn1.x; // 1
Crockford avoids the 'new' operator because of dangers with the value of 'this'. In addition, it allows for encapsulation of values, which is typically more difficult in JS. For example, if x and y are really meant to be more private, you could do this:
var chessPiece = function(x, y) {
var obj = {};
var xCoord = x;
var yCoord = y;
obj.getNotation = function() {
return 'abcdefgh'[xCoord] + '12345678'[yCoord];
};
obj.moveX = function (amount) {
x += amount;
}
return obj;
}
var pawn1 = chessPiece(1, 0);
pawn1.getNotation(); // 'b1';
pawn1.move(2);
pawn1.getNotation(); // 'd1';
pawn1.x; // undefined
Since xCoord and yCoord are trapped in closure scope, getNotation and moveX both work with xCoord and yCoord acting like private variables. Crockford has other tips and uses for this technique as well.

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

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();
});

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