简体   繁体   中英

Performance issue when assigning the same function to multiple variables in JavaScript

[Edited] Important! Function is treated as object, not value. So this question is invalid because it is based on a wrong assumption. This edit serves as a note to avoid confusing anyone who read this question.

Let's say I have a function expression of foo

var foo = function() {
    return this.member;
}

and I have the following class and instantiate many objects of it with "foo" as the callback function.

var simpleClass = function(callback) {
    this.member = "I am an instance variable";
    this.callback = callback;
}
var a = new simpleClass(foo);
var b = new simpleClass(foo);
var c = new simpleClass(foo);
.
.
.

Since in JavaScript arguments are passed by value, we are copying the value ([Edited]actually it should be object) of foo to a, b, c and other variables' callback. If my understanding is correct, then foo will be copied n times, each occupying certain memory space for each object.

Base on this understanding, I have some performance questions regarding this situation:

  1. Does copying functions to multiple variables harm the performance?

Since each copies of "foo" as simpleClass object's "callback" occupies space, if there are really many simpleClass object(eg in a DOM library I have thousands of DOM objects which has the same function css()), will it harm the performance significantly? Or most JavaScript engine has mechanism to tackle this situation and it generally won't harm at all?

  1. In situation where potentially hundreds or thousands of object will be created. Is it always a good practice to put those shared functions to the prototype of an object?

Since all the object instance share the same class prototype, if we put the "foo" function to the prototype of simpleClass, then there should have only one copy of the "foo" and every object instance will just execute the prototype copy of "foo" when needed. Is this a good practice we should follow?

I try to search for similar keywords but couldn't find the right wordings to find the solution to this problem. Please correct my wordings if I make anything unclear. And of course if I have any misunderstandings please correct me too. I appreciate everyone's help.

I don't understand this well enough to give you an authoritative answer but I can say this:

then foo will be copied n times, each occupying certain memory space for each object.

This is incorrect. foo is a variable pointing to a function. foo is not the function, if you did var bar = foo , bar now also points to the function, the same function. So the function is not copied. A reference to the function is assigned to this.callback .

  1. In situation where potentially hundreds or thousands of object will be created. Is it always a good practice to put those shared functions to the prototype of an object?

What is and isn't good practise in JavaScript is up for debate. Some people like to use class/prototype, other people use object literals. It's definitly true though that prototype can help reduce the memory footprint of your application. See it like this: if you're using prototype you're giving the JavaScript engine more information about the object, ie. that your object is similar to all these other objects. The JavaScript engine should be able to make optimizations based on that. I can't say too much about the exact numbers, it might vary wildly per vendor.


Your code sample is equivalent to this:

function foo() {}
function myClass() {
    this.foo = foo;
}
var instance = new myClass();

If you used prototypes you'd write:

function myClass() {}
myClass.prototype.foo = function () {};
var instance = new myClass();

If you used object literals you'd have:

function foo() {};
function create_myClass() {
    return {
        foo: foo
    };
}
var instance = create_myClass();

In all the cases above the function foo is never copied . In these cases below you do create a new copy of foo every time:

function myClass() {
    this.foo = function () {}; // new copy every time
}
var instance = new myClass();

function create_myClass() {
    return {
        foo: function () {}; // new copy every time
    };
}

As for performance. This is the tip I always give: don't start optimizing until you run into a measurable problem. Always measure with real data. Additionally, if you think your way of doing things is good then it's likely that JavaScript engine vendors will optimize for that method.

In javascript reference is copied not the object itself so you can't assign the value to callback to change the function from inside constructor. You your code all those object will share the function, look at this snipet:

 var foo = function() { return this.member; } var simpleClass = function(callback) { this.member = "I am an instance variable"; this.callback = callback; } var a = new simpleClass(foo); var b = new simpleClass(foo); alert(a.callback === b.callback ? 'shared' : 'not shared'); 

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