I'm having difficulties understanding behavior of Javascript.
Code:
function getPosition(element){
var position = {
x:$(".line div").has(element).index(),
y:$(".line").has(element).index()
};
console.log(position.y);
console.log(position)
return position;
}
Now while calling it from function I'm getting results like this:
0
Object
x: 8
y: 3
What I don't understand is how is it possible to change object attributes when trying to access it via object reference, but not directly.
But when I call same function from console I get this:
0
Object
x: 8
y: 0
This is the same element passed to function. And it seems that it fails always when X or Y is 0(zero), when it's another number it's ok.
Could anyone explain what I'm doing wrong? Or is it somekind of JS bug? O_o
EDIT:
So I finally found out what the problem was. I always thought that I was passing values but unfortunately I was wrong all the time. During some searches on stackoverflow, I found topic about JS values and references.
If anyone is interested and too lazy to read the topic, you can look at this example. It's pretty much self explanatory.
function test(){
var a = 5;
var b = a; //b now has value of 5
console.log("a:"+a+":b:"+b);
b = 4;//a still has value of 5 and b is assinged to 4
console.log("a:"+a+":b:"+b);
var c = {val:1};
var d = c; //d now has reference to c
d.val = 2; //c.val changes because it is a reference
console.log(c);
}
EDIT2:
oh and by the way, how can I mark my question as answered?
console.log delays converting values to string until the application slows down so that logging doesn't slow down the application unnecessarily.
If the console.log(position) is showing a value that is different from that at the time console.log was called its because the position has been modified between the call and the time the console widget decided to format the value for display.
You can see this by trying the following HTML:
<script>
// Emits the JSON form when converted to a string.
var obj = {
x: 1,
toString: function () {
return JSON.stringify(this);
}
};
console.log(obj); // Often {x:2}
console.log("" + obj); // Reliably {x:1}
obj.x = 2;
</script>
Look for code that does something like
obj = getPosition(...);
...
obj.y = <expression that evaluates to zero>
Alternatively, you can force eager formatting by changing
console.log(position)
to
console.log("" + position)
So I finally found out what the problem was. I always thought that I was passing values but unfortunately I was wrong all the time. During some searches on stackoverflow, I found topic about JS values and references.
If anyone is interested and too lazy to read the topic, you can look at this example. It's pretty much self explanatory.
function test(){
var a = 5;
var b = a; //b now has value of 5
console.log("a:"+a+":b:"+b);
b = 4;//a still has value of 5 and b is assinged to 4
console.log("a:"+a+":b:"+b);
var c = {val:1};
var d = c; //d now has reference to c
d.val = 2; //c.val changes because it is a reference
console.log(c);
}
Related
I am making a simple game in js which consists of a grid and some cells
This is what it currently looks like and it works perfectly. The thing is that while making this I set the margin to 0 but I
would like to move the canvas to center. To do that, I got the margin from this function
var test = document.querySelector('.test');
var left_margin = window.getComputedStyle(test).getPropertyValue("margin-
left "); // returns margin e.g. '655px'
left_margin = left_margin.match(/\d+/);
Then I made some changes in the whole thing to account for this offset but for some reason when I try to add the offset to the x-axis, it returns NaN. To make sure there wasnt some problem I performed some basic mathematical operations on this value and they worked. Can someone tell me what is going on with this? and also, is there a simple way to just redefine the origin for an element(a canvas in my case), to avoid this hassle?
Edit:
I dont understand this. When i simply do var a = blockWidth + 0;The game doesnt start and then do console.log(a) this also return NaN. and i get**(Uncaught TypeError: Cannot set property 'strokeStyle' of undefined)**
function grid(){
var a = blockWidth + left_margin;
var b = blockHeight;
while (a != widthWin){
drawLine(a, 0, a, heightWin, 1, 'gray');
a += blockWidth;
}
while (b != heightWin){
drawLine(left_margin, b, widthWin+left_margin, b, 1, 'gray');
b += blockHeight;
}
}
What you get with
left_margin = left_margin.match(/\d+/);
is an array ["655"] not an int as you are assuming.
Therefore, you need to access its first element and parse it to a number before using it for doing any math:
left_margin = parseInt(left_margin.match(/\d+/)[0]);
It appears that JavaScript objects aren't compatible with the ^ XOR operator. So is there any way to create an XOR doubly linked list?
I can do regular single/double linked lists fine. And I've searched on both SO and Google without success, so my guess is that it isn't possible. Or perhaps no one really cares about XOR lists...
var node = function(data, xor){
this.data = data;
this.xor = xor;
}
var myNode=new node('data', 0);
console.log(0 ^ myNode); // shows 0, should show myNode
console.log(null ^ myNode); // shows 0, too
console.log(5 ^ 0); // 5 as expected
You can't implement a proper XOR linked list in JavaScript, because you can't access an object's memory address.
There's not really a practical reason to do this in JavaScript, either. From what I understand, the only benefit of an XOR linked list is a slightly reduced memory footprint. The amount of memory you would save with such a structure in JavaScript is offset by the overhead of the objects themselves.
Someone asked the same question about Python once; the answer also applies to JavaScript.
Solely for the purpose of practice, I wrote a bit to simulate pointers using a map. Obviously, this is not for production code.
var node = function(data, xor){
this.data = data;
this.xor = xor;
}
var pointerFactory = function(){
var pointers = {};
var pointerCount = 0;
this.get_pointer = function(node){
if (pointers.hasOwnProperty(node)) return pointers[node];
pointerCount++;
pointers[node]=pointerCount;
pointers[pointerCount]=node;
return pointerCount;
}
this.dereference_pointer = function(pointer){
return (pointers.hasOwnProperty(pointer)) ? pointers[pointer] : null;
}
}
var myNode = new node('my data', 0);
var pf = new pointerFactory();
var p = pf.get_pointer(myNode);
console.log(pf.dereference_pointer(p).data); // my data
console.log(pf.dereference_pointer(2)); //null
console.log(0 ^ p); // 1
console.log(p ^ p); // 0
I have the following object:
var data = {
'buyRate': ['Buy Rate', 0.15, 'enteredData.numberOfTransactions * enteredData.buyRate',
'setupFee': ['Setup Fee', 0.00, 'enteredData.setupFee'],
'numberOfTransactions': ['# of Trans.', 10, 'enteredData.numberOfTransactions']
}
enteredData is another object that pulls values from user inputs. Created after this object but it does exist
What I want to do is use the third position in the array as a formula to calculate a 'Total' which is displayed using a script like this (I run this after the object is created so the object keys are not undefined):
for (var key in data) {
var formula = data[key][2];
// evaluate the formula by some magic
var sum = new Function('return '+formula);
document.getElementBy(key+'Total').value = sum;
}
Because I am working in Google Sites using eval() is not an option for me. I've tried using var sum = new Function('return '+formula); and it's not working for me. I don't get any errors. And console.log displays (no other information):
function anonymous() {
return data.numberOfTransactions * data.buyRate
}
Not sure how else to approach this problem. Would appreciate a push in the correct direction.
If Google disallows eval, I would guess they also disallow running user-supplied code using your Function trick.
However, if this is not the case, you need to slightly change your function. MDN states:
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called.
You'd therefore need to pass the correct variables, like this:
for (var key in data) {
var formula = data[key][2];
// create function
var my_func = new Function('data', 'return ' + formula);
// pass data explicitely
var sum = my_func(data);
document.getElementBy(key+'Total').value = sum;
}
The answers here helped me but after I figured out that Google Sites also don't allow creating function constructors I approached this a different way that allowed me keep the logic that I wanted.
Below the is the updated object. I simply rewrote my formula as a tiny function that I can call:
var data = {
'buyRate': ['Buy Rate', 0.15, function() {return enteredData.numberOfTransactions * enteredData.buyRate;},
'setupFee': ['Setup Fee', 0.00, function() {return enteredData.setupFee;}],
'numberOfTransactions': ['# of Trans.', 10, function() {return enteredData.numberOfTransactions;}]
}
This will run the formula every time I call it and not when the object is rendered.
My updated For...in loop looks like this:
for (var key in data) {
var sum = data[key][2];
document.getElementBy(key+'Total').value = sum();
}
Hope this will help someone in the future.
I am having a little bit of trouble understanding Higher Order Functions in javascript.
Can someone explain to me the difference of what's going on in these two situations?
Scenario 1:
// A function that takes in a number (x) and adds one to it.
function doMath(x){
return function (x){
return x + 1;
}
}
var didMath = doMath(5);
console.log(didMath()); // returns error
var didMath = doMath();
console.log(didMath(5)); // returns 6
var didMath = doMath(100);
console.log(didMath(5)); // still returns 6
Scenario 2:
function doMath2(x,callback){
return callback(x);
}
function add(x){
return x + 1;
}
console.log(doMath2(5,add)); // returns 6, works perfectly fine
I was under the impression that closures have access to parameters from their containing functions. Why is it that in Scenario 1, the "x" param in doMath is not accessible by the contained function?
what is happening here is you are never storing the value of x, you always return a new function, see this example it should work as you expect and maybe helps you to undersant
function doMath(x){
var y = x;
return function(y){
return y + 1;
}
}
In scenario 1
The first one outputs an error because the returned function expects an argument and you don't give one. If you remove the argument it works:
// A function that takes in a number (x) and adds one to it.
function doMath(x){
return function (){ // <--- here
return x + 1;
}
}
var didMath = doMath(5);
console.log(didMath());
In your two other examples you do give an argument and that is the one taken into account. Not the value that you give as parameter to doMath()
This is a simplification of something that I've come up against in a larger project so I hope it makes sense.
I have two Objects:
FirstObj = {
data : [],
init : function()
{
for(var a = 0; a < 20; a++)
{
this.data[a] = 1;
}
}
};
SecondObj = {
init : function()
{
var cell = FirstObj.data[0];
cell = 0;
}
};
I then call the two init methods and log the results:
(function(){
FirstObj.init();
SecondObj.init();
console.log(FirstObj.data);
})()
Now, I was assuming - based on my basis in Actionscript - that the log would show an Array in which the first item is a 0 and the rest all 1 but the 0 does not seem to stick.
Why does the assignment of the 0 value not succeed here and yet works fine if, instead of cell = 0 I target directly at FirstObj.data[0] = 0.
I'm guessing this is a scope thing and I can work round it but I'm trying to get a proper understanding of how JS actually handles this stuff, especially when lumping code into Objects like this (as an aside, is this a good approach in peoples general opinion?).
Thank for any help.
Numbers in JavaScript are something called primitive value types (alongside strings, booleans null and undefined).
This means, that when you do
var cell = FirstObj.data[0];
You're passing the value in FirstObj.data[0] and not a refernece to it.
What you're doing is like:
var x = 5;
var y = x; // y is now 5
y = 4; // y is 4, x is still 5.
Of course, something like FirstObj.data[0] = 0 should work.
Array indexing returns values in Javascript, not references. It means that once data[0] is assigned to cell, further modification of cell will not affect data[0].
Assigning the array itself would result in the behavior you're looking for:
SecondObj = {
init : function()
{
var cells = FirstObj.data;
cells[0] = 0; // Will also affect data[0].
}
};