2

I was pondering something earlier. I wanted to check if a function had already been put into an array. If so throw an exception. I did this little test with the console...

enter image description here

So I guess I could say that the objects are always just references, and after setting a as x I could change x and a would be effected as well?

Would this mean that the condition x = a no matter what, which is what I want.

Using this to check if the function/object is already in the array I could just do this correct...

enter image description here

Is there a better way to do this?

Would this also mean that if I pass a variable to a function and mutate it in that function it will be mutated outside of that function as well?

EDIT

I guess I am right about the mutation with this little test. But I don't get why its bar in the first log in the second example

enter image description here

enter image description here

EDIT END

Example 1:

var x = function(){console.log("hello")}; var a = function(){console.log("hello")}; 

console.log(x == a); //comes out false

//Set a as x
a = x; 

console.log(x == a); //comes out true

Example 2:

Array.prototype.Contains = Array.prototype.Contains || function (obj) {
    return this.indexOf(obj) != -1;
};

var x = function(){console.log("hello")}; var a = function(){console.log("hello")}; 

var z = a;

console.log(x == a); //comes out false

var l = [];
l.push(x);

//Set a as x
a = x; 

l.push(a);

console.log(x == a); //comes out true

console.log(l.Contains(x)); //Should come out true
console.log(l.Contains(a)); //Should come out true
console.log(l.Contains(z)); //Should come out false
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
FabianCook
  • 20,269
  • 16
  • 67
  • 115

3 Answers3

3

Your question isn't entirely clear to me but I'll try to answer as best I can.

Improving the function

Your function could be simplified to leverage the indexOf function.

Array.prototype.Contains = Array.prototype.Contains || function (obj) {
    return this.indexOf(obj) >= 0;
};

Also I want to point out that in your implementation you're looping through everything when you could exit early by returning inside the if.

Array.prototype.Contains = Array.prototype.Contains || function (obj) {
    var i;
    for (i = 0; i < this.length; i += 1) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
};

x == a

I think you understand but just want to clarify, x and a are different originally because they are referencing different functions. When you set x = a they are both pointing at the function declared originally in x and are therefore the same. Even thought the functions are identical in terms of implementation, they were both constructed and then placed in different parts of memory.

Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
1

When you do this:

var x = function(){console.log("hello")}; var a = function(){console.log("hello")}

x and a point to different functions. Even if you compare them for equality, they are not equal as all equality checking does here is see if they point to the same function or not - there is no attempt made to see if they would produce the same output when run or not (that is almost impossible to do in general, after all).

When you do something like x = a, x now references whatever a is referencing - the same object. So now they compare equal.

If you need to see if a function already exists in an array, I suggest instead of just placing arrays in a big list, you create a dictionary (hashmap, hashtable, whatever you want to call it) that uses strings as keys as function as values. The key would be the 'name' of a function - whenever you make that function you'd use the same name, and names in different places in memory but with the same characters in them WILL compare equal.

Patashu
  • 21,443
  • 3
  • 45
  • 53
  • All the functions names are the same. Just that they have different values. They are initially just properties of variables. – FabianCook Mar 18 '13 at 02:36
  • @SmartLemon So - their key (what distinguishes them) is their value! – Patashu Mar 18 '13 at 02:37
  • Makes sense. But the object will have more weight as you would need to store an extra string. Also the property is deleted once used. – FabianCook Mar 18 '13 at 02:41
  • @SmartLemon Javascript uses managed memory, so once anything (string or property or otherwise) is not in use it will be garbage collected. If you store strings (or functions or anything) past the point when you still need them, well, that's your problem and you can avoid that! – Patashu Mar 18 '13 at 02:44
  • The arrays are properties of a global variable that is kept throughout the lifecycle of the page. Which is why I delete them early. What would you suggest to avoid it? – FabianCook Mar 18 '13 at 02:47
1

You're really confused. Everything in JavaScript (except for primitive data types, null and undefined) is an object, and objects are stored in variables as reference. Read the following answer to know more about the differences between the two: https://stackoverflow.com/a/13268731/783743

When you define two identical functions (in your case x and a) JavaScript sees them as separate functions. This is because in addition to the function body a function also maintains its own environment and state. Hence x and a are not the same function which is why x === a returns false.

By setting x = a you're essentially copying the reference stored in a into x. Hence they now point to the same function (which is the function a was originally referring to). The function x was originally referring to is now lost and will eventually be garbage collected. Thus x === a now returns true.

BTW you don't need to create a special Contains function to check whether an object is already inside an array. Just use indexOf:

var array = [];
function x() {}

array.indexOf(x); // returns -1
array.push(x);
array.indexOf(x); // returns 0

If the index is less than 0 the object is not in the array.

If you want to check whether the function body of two functions is the same then use this function:

function sameFunctionBody(a, b) {
    return String(a) === String(b);
}

Now console.log(sameFunctionBody(x, a)) will return true as long as both the functions are exactly the same (including whitespace, parameters, function name, etc).

Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299