tc39 / proposal-optional-chaining

Home Page:https://tc39.github.io/proposal-optional-chaining/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

replace Object wrapper strange behiavior

jonlepage opened this issue · comments

I very love this new addon.
But something strange append in some case.
Should no more need manually type Object wrapper in some case with this addon.
Example Number
Test case

Number.prototype.isFinite = function() {
    return Number.isFinite(this)
}

var n1 = 100;
var n2 = Infinity;
var n3 = null;
if(n1?.isFinite()){ }; // return false !
if(n2?.isFinite()){ };
if(n3?.isFinite()){ };

That's not related to optional chaining, n1.isFinite() also returns false.

This happens because when you access n1.isFinite, the number primitive gets converted ("boxed") to a Number object and, in loose mode, your isFinite method is then called with this being the "boxed" Number object instead of the primitive number 100.

Three ways you can get around this

  1. Use isFinite instead of Number.isFinite
  2. Coerce the boxed object to number value first: return Number.isFinite(Number(this))
  3. Use strict mode
 Number.prototype.isFinite = function() {
    'use strict';
    return Number.isFinite(this)
}

Anyway, not an optional chaining issue.

I have nothing to add to @noppa’s answer, except that, if I had to give “three ways you can get around this”, they would be:

  1. Use strict mode
  2. Use strict mode
  3. Use strict mode

Strict mode eliminates the trap you've fallen into (namely, autoboxing of primitive values when used as target of method calls), and resolves other gotchas as well.

(I echo the recommendation)

To clarify, strict mode doesn't change autoboxing in the general case - (100).toString(), eg, works the same in any mode. What strict mode does do is make assigning to a property on an autoboxed primitive an error, rather than a silent failure; it also avoids autoboxing a receiver, so that the this will be the primitive value in strict mode (where in sloppy mode, it would be the boxed object).

I'm not sure this has any relation to optional chaining :-)