New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: use Array.isArray instead of instanceof Array to handle crazy JS better #487

Closed
AZon8 opened this Issue Jan 18, 2016 · 2 comments

Comments

Projects
None yet
3 participants
@AZon8

AZon8 commented Jan 18, 2016

I had some problems with decoding json in a situation where i was passing in node.js Arrays.

The problem originated because of this :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

Different scope have different execution environments. This means that they have different built-ins (different global object, different constructors, etc.). This may result in unexpected results. For instance, [] instanceof window.frames[0].Array will return false, because Array.prototype !== window.frames[0].Array and arrays inherit from the former. This may not make sense at first but when you start dealing with multiple frames or windows in your script and pass objects from one context to another via functions, this will be a valid and strong issue. For instance, you can securely check if a given object is in fact an Array using Array.isArray(myObj)

The solution for me was to replace all the Native/Json.js
value instanceof Array with Array.isArray(value)

@evancz

This comment has been minimized.

Show comment
Hide comment
@evancz

evancz Jun 25, 2016

Member

What are the differences in performance of these two approaches?

Member

evancz commented Jun 25, 2016

What are the differences in performance of these two approaches?

@evancz evancz changed the title from Json decode failing for arrays in NWJS project to Proposal: use Array.isArray instead of instanceof Array to handle crazy JS better Jun 25, 2016

@lukewestby

This comment has been minimized.

Show comment
Hide comment
@lukewestby

lukewestby Aug 11, 2016

Member

http://jsbin.com/muqaciyozi/1/edit?js,console

I did some simple benchmarking with benchmark.js in various browsers. Here toString refers to the technique Object.prototype.toString.call(obj) === '[object Array]'. This is included with the existing instanceof and the proposed Array.isArray. The tradeoffs seem to be: instanceof is the fastest but does not behave across execution contexts. Array.isArray is consistent but slower than instanceof and also not supported prior to IE9. Using Object.prototype.toString is consistent across contexts, broadly supported in browsers, but is notably slower than the other two options.

If switching to Array.isArray is desirable then it is possible to polyfill it with the toString method for IE8 and below.

Mean execution times according to benchmark.js:

[] instanceof Array {} instanceof Array Array.isArray([]) Array.isArray({}) toString([]) === '[object Array]' toString({}) === '[object Array]'
Chrome 52 1.7876434065161444e-8 2.330498325001016e-8 2.436932813655087e-8 3.003167409610475e-8 6.593245721914357e-7 4.105239635961423e-7
Safari 9.1 4.4020788002132974e-8 3.5085045152805906e-8 5.478782940038529e-8 4.453426066743071e-8 8.996925572126374e-8 6.33213332061942e-8
Firefox 44 7.198862145315244e-10 7.910334331974017e-10 7.209425173911308e-10 8.002760240146521e-10 3.063021952664718e-8 2.2586274411698193e-8
IE 11 1.64349e-7 6.09866e-8 2.00234e-7 9.76242e-8 3.03752e-7 1.28477e-7
Member

lukewestby commented Aug 11, 2016

http://jsbin.com/muqaciyozi/1/edit?js,console

I did some simple benchmarking with benchmark.js in various browsers. Here toString refers to the technique Object.prototype.toString.call(obj) === '[object Array]'. This is included with the existing instanceof and the proposed Array.isArray. The tradeoffs seem to be: instanceof is the fastest but does not behave across execution contexts. Array.isArray is consistent but slower than instanceof and also not supported prior to IE9. Using Object.prototype.toString is consistent across contexts, broadly supported in browsers, but is notably slower than the other two options.

If switching to Array.isArray is desirable then it is possible to polyfill it with the toString method for IE8 and below.

Mean execution times according to benchmark.js:

[] instanceof Array {} instanceof Array Array.isArray([]) Array.isArray({}) toString([]) === '[object Array]' toString({}) === '[object Array]'
Chrome 52 1.7876434065161444e-8 2.330498325001016e-8 2.436932813655087e-8 3.003167409610475e-8 6.593245721914357e-7 4.105239635961423e-7
Safari 9.1 4.4020788002132974e-8 3.5085045152805906e-8 5.478782940038529e-8 4.453426066743071e-8 8.996925572126374e-8 6.33213332061942e-8
Firefox 44 7.198862145315244e-10 7.910334331974017e-10 7.209425173911308e-10 8.002760240146521e-10 3.063021952664718e-8 2.2586274411698193e-8
IE 11 1.64349e-7 6.09866e-8 2.00234e-7 9.76242e-8 3.03752e-7 1.28477e-7

@evancz evancz closed this in ff31925 Jul 10, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment