Subclassing native class and instanceof operator
In which engine did you try this? Please refer to kangax.github.io/compat-table/es6 under "Subclassing" to see if your browser supports subclassing builtins yet.
The correct spec behavior is to return an instance of MyError
. Step 7 in
your example is not equivalent to calling Error
without new
, which
seems to be your assumption. The newTarget
parameter passed to
Construct
is used to determine the prototype of the final object, and in
this context newTarget
would be MyError
.
Babel does not support extending builtins by default because it is difficult to transpile properly and would add more boilerplate in all class cases, even those which do not require logic to handle native extension. If you need builtin extension support, the only way at the moment is to explicitly enable it via a plugin like www.npmjs.com/package/babel
On May 31, 2016, at 3:25 AM, Logan Smyth <loganfsmyth at gmail.com> wrote:
The correct spec behavior is to return an instance of
MyError
. Step 7 in your example is not equivalent to callingError
withoutnew
, which seems to be your assumption. ThenewTarget
parameter passed toConstruct
is used to determine the prototype of the final object, and in this contextnewTarget
would beMyError
.Babel does not support extending builtins by default because it is difficult to transpile properly and would add more boilerplate in all class cases, even those which do not require logic to handle native extension. If you need builtin extension support, the only way at the moment is to explicitly enable it via a plugin like www.npmjs.com/package/babel-plugin-transform-builtin-extend, www.npmjs.com/package/babel-plugin-transform-builtin-extend
On Mon, May 30, 2016 at 11:56 PM, Gray Zhang <otakustay at gmail.com <mailto:otakustay at gmail.com>> wrote: I know NodeJS outputs
true
in this case, but my problem is from the spec it seemsfalse
is the correct result, or am I missing some chapters in spec?Jordan Harband <ljharb at gmail.com <mailto:ljharb at gmail.com>>于2016年5月31日周二 下午2:47写道: In which engine did you try this? Please refer to kangax.github.io/compat-table/es6, kangax.github.io/compat-table/es6 under "Subclassing" to see if your browser supports subclassing builtins yet.
On Mon, May 30, 2016 at 11:32 PM, Gray Zhang <otakustay at gmail.com <mailto:otakustay at gmail.com>> wrote: Recently I encountered an issue about subclassing Error and instance operator, my simplified code is:
class MyError extends Error { constructor() { super('my error’); } } let error = new MyError(); console.log(error instanceof MyError); console.log(error.constructor);
Surprisingly the output is
false
andfunction Error() { [native code] }
I dived into the ECMAScript 2015 spec and find the behavior is correct, chapter 12.3.5.1 says: SuperCall : super Arguments Let newTarget be GetNewTarget www.ecma-international.org/ecma-262/6.0/index.html#sec-getnewtarget(). If newTarget is undefined, throw a ReferenceError exception. Let func be GetSuperConstructor www.ecma-international.org/ecma-262/6.0/index.html#sec-getsuperconstructor(). ReturnIfAbrupt www.ecma-international.org/ecma-262/6.0/index.html#sec-returnifabrupt(func). Let argList be ArgumentListEvaluation of Arguments. ReturnIfAbrupt www.ecma-international.org/ecma-262/6.0/index.html#sec-returnifabrupt(argList). Let result be Construct www.ecma-international.org/ecma-262/6.0/index.html#sec-construct(func, argList, newTarget). ReturnIfAbrupt www.ecma-international.org/ecma-262/6.0/index.html#sec-returnifabrupt(result). Let thisER be GetThisEnvironment www.ecma-international.org/ecma-262/6.0/index.html#sec-getthisenvironment( ). Return thisER.BindThisValue www.ecma-international.org/ecma-262/6.0/index.html#sec-bindthisvalue(result). Since Error can be called as a function without new operator, the result of step 7 is an error instance rather than undefined, so this error instance becomes
this
value ofthisER
and then returned as the result of new MyError constructor.
Huh?? Step 7 isn’t a [[Call]] it is a [[Construct]]. Syntactic rules such as “must use new to invoke a constructor” can’t apply at the level of pseudo-code.
The problem is, the spec also said "The Error constructor is designed to be subclassable." so I think instanceof should work correctly on subclasses, however it fails now.
It is specified to work. Your implementation must be wrong or imp complete.
This also comes to Map, Set, Array and Object constructors.
Also should work
Recently I encountered an issue about subclassing Error and instance operator, my simplified code is:
Surprisingly the output is
false
andfunction Error() { [native code] }
I dived into the ECMAScript 2015 spec and find the behavior is correct, chapter 12.3.5.1 says: SuperCall : super Arguments
Since Error can be called as a function without new operator, the result of step 7 is an error instance rather than undefined, so this error instance becomes
this
value ofthisER
and then returned as the result of new MyError constructor.The problem is, the spec also said "The Error constructor is designed to be subclassable." so I think instanceof should work correctly on subclasses, however it fails now.
This also comes to Map, Set, Array and Object constructors.
Babel 6.7.7 has the correct behavior which fails on instanceof operator but it really introduces some troubles, is this by design and how could I avoid such issues?