2

While comparing functions in Javascript, am thinking that it compares the memory at which function is defined to cross-check that the given 2 functions are equal.
So, was trying to compare a member function by accessing it from 2 different instances of same object as below:

function testFn(name) {
    var name = name;
    var self = this;
    self.compareFn = function() {
        console.info(name);
    }    
}

var fn1 = new testFn('fn1');
var fn2 = new testFn('fn2');
console.info(fn1.compareFn == fn2.compareFn);  //Returns false

Have defined an object testFn with one member function ("compareFn") and created 2 instances of it (fn1,fn2) and but on comparing "fn1.compareFn == fn2.compareFn",it fails.

Remember, that member function is shared across multiple instances and only local variables will be allocated separately.
Please suggest why this comparison fails.

Naga Kiran
  • 8,585
  • 5
  • 43
  • 53

6 Answers6

1

That method is actually created for each instance. You want to declare it on the object's prototype. See below.

var testFn = function(name) {
    this.name = name;
}

testFn.prototype.compareFn = function() {
   console.info(this.name);
}

var fn1 = new testFn('fn1');
var fn2 = new testFn('fn2');
console.info(fn1.compareFn == fn2.compareFn);  //Returns true
Mike Pugh
  • 6,787
  • 2
  • 27
  • 25
1

If you want the function to be shared across multiple instances, do it like this:

function testFn(name) {
    var self = this;
}

testFn.prototype.compareFn = function() {
  console.log(name);
};    

var fn1 = new testFn('fn1');
var fn2 = new testFn('fn2');
console.log(fn1.compareFn == fn2.compareFn); 

DEMO

rafaelcastrocouto
  • 11,781
  • 3
  • 38
  • 63
1

This fails because each time you do new testFn it is generating a new compareFn; you're not pointing to a reference outside of the constructor or inheriting from a prototype.

You can't access a variable from inside a Constructor with a shared function, because it doesn't have access to that closure. If you want to achieve a shared function you will need to move these values into a reference-able space too, i.e.

function testFn(name) {
    var vars = {}; // using object because javascript passes refs for objects
    this.vars = vars; // make `this.vars` point to `vars`
    vars.name = name; // set whatever on your object
}
testFn.prototype.compareFn = function () {
    console.info(this.vars.name); // can access `vars` through ref of `this.vars`
};

Now

var a = new testFn('foo'), b = new testFn('bar');
a.compareFn === b.compareFn; // true;
a.compareFn(); // logs "foo"
Paul S.
  • 64,864
  • 9
  • 122
  • 138
1

I think the reason it comes out as false is because, here at least, instead of testing for equality of the outcome of the 'source code' it is testing for the location of memory they both refer to. The reason for this is because it can't test for equality in any other way.

Different ways to measure equality:

  • Testing for the return value would be done by running the function:

    fn1.compareFn() == fn2.compareFn() //true

  • Testing for the source would be done by calling toString() (note: this is not standardised among browsers!):

    fn1.compareFn.toString() == fn2.compareFn.toString() //true

However, as they are different instances (you are not calling testFn == testFn or fn1.compareFn == fn1.compareFn), they refer to different memory locations so the test for equality comes out as false.

More info about that can be found on this question too: 'how compare two static function are equal or not in javascript'.

Also as a note, you should be using a triple equals (===) rather than a 'double equals' as the latter does not test for equality of type (i.e. checking that 2 variables are both numbers, as well as having the value 5).

Community
  • 1
  • 1
user2521439
  • 1,405
  • 2
  • 13
  • 19
0

Every time you call the function testFn, it creates a new variable and assigns a function to it...

So yes, they are identical functions, but they are not the same thing.

There are a couple of other patterns you could use to get the results you'd like. In this case, you'd want to use the prototypical pattern:

// Constructors should start with an upper case letter
function TestFn(name) {
  this.name = name;
}

TestFn.prototype.testFn = function() {
  console.info(this.name);
}    


var fn1 = new TestFn('fn1');
var fn2 = new TestFn('fn2');
console.info(fn1.compareFn == fn2.compareFn);  // Returns true
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
0
function testFn(name) {
    this.name = name;
}

testFn.prototype.compareFn = function() {
    console.info(name);
}

var fn1 = new testFn('fn1');
var fn2 = new testFn('fn2');
console.info(fn1.compareFn == fn2.compareFn);  //Returns TRUE

You are redefining the function each time the constructor is called, therefore the methods are not equal. By assigning them to the prototype, it is the same method.

If you're interested in keeping name (or other variables or functions private), then check out this SO answer.

Community
  • 1
  • 1
Ben Jacobs
  • 2,526
  • 4
  • 24
  • 34