'use strict'
declarations in your scripts.
As seen in jQuery
This library is the most known/common example where$(something)
will actually generate an instanceof jQuery
variable even without using new
.
Some background
Since basically ever, JavaScript constructors suchArray
, Object
, Function
and RegExp
do not distinguish between new Array/Object/Function/RegExp
or just the same without new
, and there are exceptions for Date
, where it always returns the same instance if invoked without new
, and primitives wrappers such Boolean
, Number
, or String
, where the meaning is very different: it's casting VS value wrapper when new
is used.
This behavior could be somehow desired when we'd like to obtain the exact same return type when a generic constructor is invoked either via new
or not.
Handy "use strict"
Because of its guard against the execution context, wherethis
would be undefined
instead of the global window
object, we can use such behavior to simplify the famous pattern.
// basic use strict feature function Constructor() {'use strict'; return this || new Constructor; }This is basically the easiest way to replicate this pre-use-strict era pattern:
function Constructor() { return this instanceof Constructor ? this : new Constructor ; }The benchmark shows no impact on Safari, but quite a gap between the old and the new pattern in Chrome. Good news is, who cares, the trick is to write less and reduce code size so if it's even faster, it's just a strawberry on top.
A different behavior
In case somebody will useConstructor.call(anotherObject)
the instance will be used inside the constructor instead of being ignored via good old pattern.This is actually not necessarily an undesired side effect because it actually lets us reuse constructors to initialize properties with mixins too, in case the initializzation is needed.
// old pattern ... function Constructor(value) { if (!(this instanceof Constructor)) { return new Constructor(value); } this.property = value; } // later on ... var mixedObject = {}; Constructor.call(mixedObject, 123); mixedObject.property; // undefinedUsing initial pattern we basically do nothing except creating a new instance that will be lost in the process while with the pattern suggested via
use strict
things play nicer than before!
// use strict function Constructor(value) {'use strict'; if (!this) return new Constructor(value); this.property = value; } // later on ... var mixedObject = {}; Constructor.call(mixedObject, 123); mixedObject.property; // 123 <=== yeah!
No backward compatible!
As easy as that, in order to be able to use this pattern the engine must be compatible with use strict directive, which is actually not a big deal in nodejs or other modern server side engines, as well as most common browsers targeted for mobile apps or extensions.In case you don't know about some target, do you remember the trick to know if the JS engine is compatible?
var hasUseStrict = (function(){'use strict';return!this}());Please note that
use strict
brings other features too so be sure other behaviors won't affect your code logic.
Wait ... what about arguments?
There are two scenarios here, the one when it does not matter:// use strict function Constructor(a, b, c) {'use strict'; if (!this) return new Constructor(a, b, c); // go on ... }and the one where exact number of arguments matter:
// use strict function Constructor(a, b, c) {'use strict'; if (!this) { return Constructor.apply( Object.create(Constructor.prototype), arguments ); } // go on ... }Take care
No comments:
Post a Comment