简体   繁体   中英

Comparing functions with .toString() in JavaScript

Consider the snippet

var dog1 = {id : 1, name : "Angus", age: 10};
var dog2 = {id : 1, name : "Angus", age: 10};

alert(dog1 == dog2);                      // ofcourse, false
alert(dog1.valueOf() == dog2.valueOf());  // ofcourse, false

In real life scenarios, dog1 & dog2 will be one and the same object.

Getting back to the real scenario,

I recently took over the project from some other developer, and for comparing objects, he has developed the following function to compare 2 objects. The project is developed purely in JavaScript.

f() which checks for the equality of 2 objects -

function compareObjs(obj1, obj2) {

            var compare = function(objA, objB, param) {

                var param_objA = objA[param];
                var param_objB = (typeof objB[param] === "undefined") ? false : objB[param];

                switch(typeof objA[param]) {

                    case "object": return (compareObjs(param_objA, param_objB));
                    case "function": return (param_objA.toString() === param_objB.toString());
                    default: return (param_objA === param_objB);
                }

            }; // internal compare helper function

            for (var parameter_name in obj1)
                if (typeof obj2[parameter_name] === "undefined" || !compare(obj1, obj2, parameter_name))
                    return false;

            for (parameter_name in obj2)
                if (typeof obj1[parameter_name] === "undefined" || !compare(obj1, obj2, parameter_name))
                    return false;

            return true;
        }

        var dog1 = {name : "Angus",

                bark : { frequency : "low" },
                age: 10
        };

        var dog2 = {name : "Angus",
                age: 10,
                bark : { frequency : "low" }
        };

        alert(compareObjs(dog1,dog2)); // true

I am confused at this line

case "function": return (param_objA.toString() === param_objB.toString());

Why for checking function equality, he has written the above code? Can someone shed light on this. Is it the correct way?

Your predecessor had good intentions, but unfortunately comparing the functions solely by their texts is not enough. You must also consider the environment in which the function was declared, because it might use closures (variables defined outside the function that the function uses).

Check out this example:

function getOne() {
  var x = 1;
  return function foo() {
    return x;
  };
}

function getTwo() {
  var x = 2;
  return function foo() {
    return x;
  }
}

var f1 = getOne(),
  f2 = getTwo();

console.log(f1 === f2); // false
console.log(f1.toString() === f2.toString()); // true
console.log(f1() === f2()); // false

In the example, f1 and f2 are function with exactly the same string representations, but one, when called, returns 1 and the other returns 2 . So the only way to correctly compare functions is by their references, ie f1 === f2 .

The thinking from the original writer was possibly that objects are only the same if they have the same functions on it.

Is it the correct way? I don't know. There are typically two ways in which object equality is useful: being the same instance and having the same content/values. This code adds the element of checking for the same functionality, but I can't really see where this would help much.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM