Using __proto__ seems to be slower than applying prototype propertiesmanually

W

webEater

I am trying to implement a class pendant, that takes a data object as
argument and then changes that object instead of extending "this" with
all the data object's data (which means copying much data to a new
object). After some benchmarks I found out, that it's much faster not
to use the conventional new operator.

protoSupport = ({}).__proto__ === Object.prototype;

G = function (data) {

if (protoSupport) data.__proto__ = G.prototype;
else {

for (var k in G.prototype) {

data[k] = G.prototype[k];
}
}
data.z = 1;
return data;
};

G.prototype = {

k: function () {

return this.a;
},

l: function () {

return this.b;
},

constructor: G
};

So we do NOT use the new operator, instead we do:

obj = {a:1, b:2};
G(obj);

INTERESTINGLY, it's even faster, when protoSupport is false and we
iterate manually over all prototype properties. Does somebody know why?
 
A

Asen Bozhilov

webEater said:
I am trying to implement a class pendant, that takes a data object as
argument and then changes that object instead of extending "this" with
all the data object's data (which means copying much data to a new
object). After some benchmarks I found out, that it's much faster not
to use the conventional new operator.

protoSupport = ({}).__proto__ === Object.prototype;

Undeclared assignment. And that test can be bogus. For example in
implementation which is not support `__proto__' anybody can do:

Object.prototype.__proto__ = Object.prototype;

And your test will lying. The better test is:

var PROTO_SUPPORT = !({__proto__ : null} instanceof Object);
G = function (data) {

Undeclared assignment.
So we do NOT use the new operator, instead we do:

obj = {a:1, b:2};
G(obj);

What is wrong on the follow code:

function G(a, b) {
this.a = a;
this.b = b;
this.z = 1;
}

G.prototype = {
constructor : G,
k : function () {
//...
},
l : function () {
//...
}
};

new G(1, 2);

Also that approach use smaller memory and is standard approach.
INTERESTINGLY, it's even faster, when protoSupport is false and we
iterate manually over all prototype properties. Does somebody know why?

Setter `__proto__` property should check for cycling chain. For
example:

var obj = {};
obj.__proto__ = obj;

During setting `__proto__' property you have reference to that object
via Scope chain and you can form cycling prototype chain, because of
that setter of `__proto__' should check for cycling chain and
performance of that is not very good.
Only object literals allow for optimization when you set `__proto__'
property because during evaluation of object literal you have not
reference to that object and therefore cannot be formed cycling chain.
For example:

var obj = {__proto__ : someObj};

So the last is safe and it allow for optimizations.
 
W

webEater

Undeclared assignment. And that test can be bogus. For example in
implementation which is not support `__proto__' anybody can do:

Object.prototype.__proto__ = Object.prototype;

And your test will lying. The better test is:

var PROTO_SUPPORT = !({__proto__ : null} instanceof Object);




Undeclared assignment.
This is an example. For a CommonJS module it will be exports.G
What is wrong on the follow code:

function G(a, b) {
    this.a = a;
    this.b = b;
    this.z = 1;

}

At first, nothing. But if a is big string, it is much faster not to
copy it to this.a - I have made some benchmarks which proof that.
G.prototype = {
    constructor : G,
    k : function () {
        //...
    },
    l : function () {
        //...
    }

};

new G(1, 2);

Also that approach use smaller memory and is standard approach.


Setter `__proto__` property should check for cycling chain. For
example:

var obj = {};
obj.__proto__ = obj;

During setting `__proto__' property you have reference to that object
via Scope chain and you can form cycling prototype chain, because of
that setter of `__proto__' should check for cycling chain and
performance of that is not very good.
Only object literals allow for optimization when you set `__proto__'
property because during evaluation of object literal you have not
reference to that object and therefore cannot be formed cycling chain.
For example:

var obj = {__proto__ : someObj};

So the last is safe and it allow for optimizations.

In the end I will use iteration over the prototype, because it's
faster an compatible with all browsers.
 
T

Thomas 'PointedEars' Lahn

webEater said:
At first, nothing. But if a is big string,

Which raises doubt as to whether that would be necessary in the first place
....
it is much faster not to copy it to this.a - I have made some benchmarks
which proof that.

Talk is cheap. Show me the code.
-- Linus Torvalds
In the end I will use iteration over the prototype, because it's
faster an compatible with all browsers.

Even faster is inheriting an object from another. You don't need the
__proto__ property for that.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top