JavaScript: using constructor without operator 'new' - javascript

Please help me to understand why the following code works:
<script>
var re = RegExp('\\ba\\b') ;
alert(re.test('a')) ;
alert(re.test('ab')) ;
</script>
In the first line there is no new operator.
As far as I know, a contructor in JavaScript is a function that initialize objects created by the operator new and they are not meant to return anything.

In general, if something is documented as being a constructor, use new with it. But in this case, RegExp has a defined "factory" behavior for the situation where you've called it as a function instead. See Section 15.10.3 of the ECMAScript (JavaScript) specification (that links to the outgoing spec; the section number is the same in the new spec, which you can download from the ECMA front page [on the right-hand side]; I don't want to directly link to a ~4MB PDF file):
15.10.3 The RegExp Constructor Called as a Function
15.10.3.1 RegExp(pattern, flags)
If pattern is an object R whose [[Class]] property is "RegExp" and flags is undefined, then return R unchanged. Otherwise call the RegExp constructor (15.10.4.1), passing it the pattern and flags arguments and return the object constructed by that constructor.
You can actually define your own JavaScript constructor functions to allow omitting the new keyword (by detecting they've been called as a function instead, and turning around and calling themselves correctly), but I wouldn't suggest it as it leads to misleading code. (And you can't do it with class syntax, you have to use the older, clunkier function syntax.)

+1 TJ Crowder has it. The ECMAScript standard goes out of its way to define behaviours for the built-in constructor functions when called as plain functions. Often it simply calls itself back as a constructor, but there are some more complicated cases.
constructors in javascript [...] are not meant to return anything
In general, a constructor can ignore this and just return an independent object:
function Thing() {
return {'foo': 1};
}
in this case you can equally use the function as a constructor (with new) or a plain function.
If the constructor doesn't return anything, as is the usual pattern for constructors, the new operator itself ensures that it returns the new object created and passed as this. In this case you must use new.
It's best not to rely on a constructor working as a bare function, and the alternative behaviours of the built-in constructors are rarely of any use, so generally you should stick with new.

Related

javascript new explained for c++ programmers

Background
I am struggling to create a function that takes a timestamp in ms from JSON and to convert it to a human-readable format. I attempted alert(Date(jsonData.timestamp).toISOString()), which resulted in "Date(...).toISOString is not a function".
But in the example for timeformating that I had looked up it worked, soon enough I noted that the pattern to be used is let myDate=new Date(...); alert(myDate.toISOString()). I tried and got an Invalid Date. So for some reason Date() and new Date() interpret the arguments differently.
I thought maybe the value I get from JSON which is a string should be passed in as a Number when I do that I end up with two different dates:
new Date(1594720804236643)); // result differs from thjsut calling Date, without new
new Date("1594720804236643")); //does not work
I figured that surly copy construciton would work and ended up with:
let myDate=Date(jsonData.timestamp);
let myDateObject=new Date(myDate);
alert(myDateObject.toISOString());
While I have a (horrible, ugly) solution, I would like to understand the nuances of new
Actual Question
Where is the difference between MyClass() and new MyClass(), a C++ programming background suggests that the difference is the only whether the object is allocated on the stack or heap. In Javascript, clearly the rules are different. On the one hand the interpretation of arguments changes, on the other hand, the set of functions available on the resulting object is different.
Here's a common pattern for a constructor that, for its own design reasons, wants to behave the same way whether it's invoked with new or not:
function NewIsOptional() {
if (this == null || !(this instanceof NewIsOptional))
return new NewIsOptional();
// normal constructor work
}
That trick works by checking this. If it's not bound (as would be the case if new were missing) or if it's bound to something of the wrong type, the code makes a recursive call via new. That pass through the constructor will see this properly bound to a new object, so it'll proceed to do its normal thing.
Now, not all constructor functions do that. I'm not sure I've ever written one, and I've typed in a lot of code. Some constructors throw an exception if they're not invoked via new. Some, for example the Symbol "constructor", throw an exception if they are invoked with new. Some constructors (like Date or Boolean) do completely different things when they're not invoked with new.
Basically there are no rules. A constructor is a function, and the code in the constructor can do whatever it wants. It can type check the parameter values and decide on different behaviors or decide to throw errors. It can call other functions, manipulate its closure if it was created inside one, and of course do mundane things like initialize object properties (which is the most usual thing to do).
Also, note that how a particular constructor function interprets its arguments, and how it behaves when it is or isn't invoked via new, are two completely orthogonal things. There are no rules for that either. A constructor is free to interpret arguments exactly the same with or without new, or it can interpret them completely differently. There are no fundamental language rules behind any of this.

What is the return value of an ES2015 constructor function?

This was a question that originally came up because I was trying to document an ES2015 class with JSDoc, and to document the class's constructor function properly I needed to know the return value and its type, and I realized that I had no idea. In researching it I couldn't find the question being asked on Stack Overflow, so I dug around looking up the details of ES2015 classes, the new operator, and the constructor function. I have found what I think might be the answer, but thought it might be helpful to post the question on SO, along with what I found, and see if others can confirm or have better answers.
To demonstrate the question, suppose one has the following code:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
var mySquare = new Rectangle(10, 10);
console.log(mySquare);//output: Object { height: 10, width: 10 }
One doesn't ever directly or explicitly call the constructor function, nor explicitly return anything from it, but it is clearly invoked and it must return something. So, what is the return value of the constructor function? And of what type is the return value?
To make things more difficult, one can't simply call the constructor and check the type of the return value, as I tried to do at first:
console.log(typeof mySquare.constructor(11, 11));//output: TypeError: class constructors must be invoked with |new|
console.log(typeof Rectangle.prototype.constructor(12, 12));//output: TypeError: class constructors must be invoked with |new|
According to MDN's reference on the new operator:
When the code new Foo(...) is executed, the following things happen:
A new object is created, inheriting from Foo.prototype.
The constructor function Foo is called with the specified arguments, and with this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
(Emphasis mine.) So it seems that the return value of the constructor function is an object, more specifically an instance of the class.
Further research showed that the return value of the constructor can be overridden by explicitly returning any object from within the constructor function (though non-object return values will be ignored, in which case the default of the newly created object reference is used.) I could not find anything to indicate that ES2015 constructors are any different than constructors prior to ES2015 classes.
This Stack Overflow post was very helpful in researching the above, particularly this article it contained a link to, though since constructor did not appear in the code in either the question nor the article, with my limited understanding of constructors that I had going into researching this they did not seem at first to answer my question. Hopefully this may clarify for others in the same situation.
Edit: The veracity of MDN's information was called into question in comments, so I researched a more definitive source. The ECMA specification says of constructors:
A constructor is an object that supports the [[Construct]] internal method.
The [[Construct]] internal method is then defined as follows:
Signature: (a List of any, Object) → Object
Description: Creates an object. Invoked via the new or super operators. The first argument to the internal method is a list containing the arguments of the operator. The second argument is the object to which the new operator was initially applied. Objects that implement this internal method are called constructors. A function object is not necessarily a constructor and such non-constructor function objects do not have a [[Construct]] internal method.
The spec states that in describing signatures such as the one above, the following convention is used: "If an internal method explicitly returns a value, its parameter list is followed by the symbol “→” and the type name of the returned value."
So, to summarize, based on the ECMA specification as quoted above, yes, constructor functions definitively do in fact return objects.

Constructor behaving differently using ES6 shorthand notation

ES6 introduced a shorthand notation to initialize objects with functions and properties.
// ES6 shorthand notation
const obj1 = {
a(b) {
console.log("ES6: obj1");
}
};
// ES5
var obj2 = {
a: function a(b) {
console.log("ES5: obj2");
}
};
obj2.a();
obj1.a();
new obj2.a();
new obj1.a();
However, these different notations behave differently, as you can see. If I do new obj1.a() in the browser (tested Chrome and Firefox), I get a TypeError: obj1.a is not a constructor. new obj2.a() behaves completely normally.
What happens here? Does anyone have an explanation, and/or links to documentation/specification?
The specification isn't very direct about explaining this, but we can follow a short chain..
We'll start at EvaluateNew, since that's the behaviour we're wondering about. Step 7 is clearly the one we're looking for here:
If IsConstructor(constructor) is false, throw a TypeError exception.
So IsConstructor is where we need to look next.
Both the summary and the steps describe this:
The abstract operation IsConstructor determines if argument, which must be an ECMAScript language value, is a function object with a [[Construct]] internal method.
If Type(argument) is not Object, return false.
If argument has a [[Construct]] internal method, return true.
Return false.
So, judging by the looks of it, our obj1.a doesn't have a [[Construct]] internal method. Let's look for where it says that it shouldn't have one..
Here's what we're looking for, PropertyDefinitionEvaluation. The first step is useful here:
Let methodDef be DefineMethod of MethodDefinition with argument object.
That calls DefineMethod with just one argument, object. Let's look at DefineMethod - here's what we need:
With parameters object and optional parameter functionPrototype.
If functionPrototype was passed as a parameter, let kind be Normal; otherwise let kind be Method.
Let closure be FunctionCreate(kind, [more arguments snipped]).
Since functionPrototype was not passed as a parameter, the kind is Method. Let's look at what FunctionCreate does with that:
If kind is not Normal, let allocKind be "non-constructor".
Else, let allocKind be "normal".
Let F be FunctionAllocate([other arguments snipped], allocKind).
Now we're getting close! We just need to look at FunctionAllocate does with allocKind (which is "non-constructor" as per the above steps), which is what gives a function all of its internal methods and such.
If functionKind is "normal", let needsConstruct be true.
Else, let needsConstruct be false.
Let F be a newly created ECMAScript function object with the internal slots listed in Table 27. All of those internal slots are initialized to undefined.
If needsConstruct is true, then
a. Set F's [[Construct]] internal method to the definition specified in 9.2.2.
b. Set the [[ConstructorKind]] internal slot of F to "base".
Finally! If we go through the relevant steps, we can see since functionKind isn't "normal", needsConstruct becomes false, and so a [[Construct]] internal method is never assigned! Then IsConstructor sees that and returns false, and so EvaluateNew fails.
MDN describes this behaviour very simply:
All method definitions are not constructors and will throw a TypeError if you try to instantiate them.
..but now you know how they aren't constructors, officially.
Seems the original discussion happens here:
https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-26.md
MM: three reasons for this:
precedent in builtins
using a method as a constructor is generally nonsense
to freeze a class, I have to freeze the .prototype of the methods on the prototype!!
and
AWB: suggestion: concise methods should be the same for both classes and object literals
strictness
enumerability
constructability
attributes
That's how both class methods and object methods became non-constructable
Methods declared using this syntax are not intended to be constructable
Reference here

Every Object is a function and every function is Object - Which is Correct?

I was reading this link JavaScript_syntax
This seems to be cyclic - that every function is an Object and every Object itself is a function. Which is the atomic one? Can someone explain in a better way?
Anything that is not a primitive type (undefined, null, number, string, boolean) is an object (or an instance) in JavaScript. That means function inherits from object.
Object instances can contain more instances which can be functions. That's what we call a "method" (since it has an automatic this variable).
Since you can't "call" every Object instance, not every object is a function.
I think this concept is often misunderstood.
A utility to visualize JS types relationship http://jstype.herokuapp.com/#/home
Javascript Data Types
Primitive types - numbers, strings, booleans, null and undefined.
All non-primitive types are object:
var foo = { };
var foo = [1, 2, 3];
var foo = function abc() { return "hello world"; };
var foo = new Number(30);
var foo = new String("Hello World");
var foo = new Boolean(true);
var foo = new RegExp(/[foo]+/);
// All 'foo` are object.
All primitive types have a corresponding Constructor Function wiz. Array, Number, String, Boolean, RegExp. As all functions are objects, they are objects too. So we can call them Constructor Function Objects.
Most of the non-primitive type has prototype property where all inherited stuff lives. Math doesn't have prototype.
All objects inherit from Object.prototype which inherits from null.
object <- Object.prototype <- null
All native functions inherit from Function.prototype which inherits from Object.prototype.
function <- Function.prototype <- Object.prototype <- null
Arrays inherit from Array.prototype which inherits from Object.prototype.
array <- Array.prototype <- Object.prototype <- null
Must read MDN: Inheritance and prototype chain
To get confused Stackoverflow: prototype in JavaScript
Stack Overflow: Function prototype explained
Every function is an object. Objects can contain functions (methods) but an object is not necessary a function.
Also Function is always a property of an object.
This mean that all functions in JavaScript is always bound to an object. If you don't specify an object to bind a function to it's bound to the window object (Also called global functions)
..fredrik
It would be better to say that in JavaScript everything can be treated as an object, that includes primitive types as well as functions types; what the JavaScript interpreter does is that it automatically promotes your primitives and functions to their object wrapper types when you interact with them.
There is also a Function object, an a number of equivalent Wrappers for the other primitives in JavaScript, that means that you can even call methods on functions instances, like:
myFunction(someArg).call(this)
That being said, not every object is in fact a function.
As others have said, functions are objects that can be passed around by reference like other javascript objects. Not all objects are functions, only those that are declared as such.
You will often see methods declared like so:
var myFunc = function(foo, bar) {
...
};
This is to reinforce the fact that the method is a function object and as such it is a property of the object where it is defined, just like any other variable you might define with var.
This is the foundation of the most important feature in javascript, closure.
Every function is an Object.
I'm not an javascript expert, but I cannot see how every Object is a function. (I can see how every object could be a function, but that's different)
Quoting from Working with Objects - MDN Docs
section Using Object Initializers last paragraph:
"In JavaScript 1.1 and earlier, you cannot use object initializers. You can create objects only using their constructor functions or using a function supplied by some other object for that purpose. See Using a Constructor Function."
meant that all objects WERE functions! Specifically, upon evaluation, instances or instantiations of functions.
Literally, ALL objects of that vintage were created syntactically with constructs like:
"newobj = new constructFunctor(arg1,arg2){this.prop1=arg1 /* etc */}(val1,val2)"
AND in the string that makes the object "newobj" there is the word "constructFunctor", the name of a function. The statement is intentionally quoted to impress the fact that it must be eval()'d to be executed. Prior to execution "newobj" is "equated to" a function because the statement MUST have one and "is" one by virtue of "constructFunctor"'s literal existence to define newobj's value upon execution. The quoting, and not, is very intentional in order to elucidate this abstraction. However, because JavaScript DOES have an eval function, this abstraction is in fact intentionally incorporated into the JavaScript language.
The legacy of this is still fundamental to JavaScript, though some syntactic short cuts have been added as "object initializers" using the shorthand notation like: "no={}". That the paragraph quoted above is still resident in the current documentation IS significant for the very reasons noted.
Furthermore, JavaScript also exemplifies the fundamental paradigms of Functional Programming. This defines everything as a function using the abstractions of Recursive Function Theory and the Lambda Calculus! For instance 0(), 1(), 2(), ... are the constant nonary functions better known as 0,1,2,3, ...
JavaScript is completely consistent with a Functional Programming Style approach rather than the common OOPS (pun intended Object Oriented Programming Style).
Just for supplementary to Aaron Digulla's answer.
In javascript not every object is a function. But Object,Array,String and many other built-in objects are functions that used with new operator to create object. I think this is what confused most people.
javascript everything is a hashtable. Ryan Dahl said this in one of his talks. thats what json is also; a hashtable definition. thats why u can access an object using array notation or object property notation. the value of the hashtable can be a function as well which is a hashtable. or rather an associative array
type Object in the console u get { [native code] } which is a hashtable
Object is an abstract data given to a class and that class is assigned to an object. Object can have properties and properties can hold values and functions.
Or simply for the sake of making it easy to understand you can say that anything that is not primitive data type (number,string, boolean, unll & undefined) can be classified as an object.
the selected answer by Aaron Digulla's is not 100% correct because it says,
Anything that is not a primitive type (undefined, null, number,
string, boolean) is an object.
but a string is an object. That is why you can do things like:
myString="Hello World";
x = myString.length;
newString = myString.toUpperCase();
link = myString.link("http://www.hello-world.com/");
And many other methods can be applied to the string object.
You could also initialize the string like:
myString = new String("Hello, World!");
But because a string is also a datatype it is much easier to initialize it by just applying a value.
Not necessarily an answer to the question ... just a clarification/correction of Aaron Digulla's answer.
The selected answer is wrong. In JavaScript everything is a function, except primitive types. Object itself is a function which is called function Object(). Use for example the following code:
<script>
alert(Object);
</script>

Is JavaScript's "new" keyword considered harmful?

In another question, a user pointed out that the new keyword was dangerous to use and proposed a solution to object creation that did not use new. I didn't believe that was true, mostly because I've used Prototype, Script.aculo.us and other excellent JavaScript libraries, and everyone of them used the new keyword.
In spite of that, yesterday I was watching Douglas Crockford's talk at YUI theater and he said the exactly same thing, that he didn't use the new keyword anymore in his code (Crockford on JavaScript - Act III: Function the Ultimate - 50:23 minutes).
Is it 'bad' to use the new keyword? What are the advantages and disadvantages of using it?
Crockford has done a lot to popularize good JavaScript techniques. His opinionated stance on key elements of the language have sparked many useful discussions. That said, there are far too many people that take each proclamation of "bad" or "harmful" as gospel, refusing to look beyond one man's opinion. It can be a bit frustrating at times.
Use of the functionality provided by the new keyword has several advantages over building each object from scratch:
Prototype inheritance. While often looked at with a mix of suspicion and derision by those accustomed to class-based OO languages, JavaScript's native inheritance technique is a simple and surprisingly effective means of code re-use. And the new keyword is the canonical (and only available cross-platform) means of using it.
Performance. This is a side-effect of #1: if I want to add 10 methods to every object I create, I could just write a creation function that manually assigns each method to each new object... Or, I could assign them to the creation function's prototype and use new to stamp out new objects. Not only is this faster (no code needed for each and every method on the prototype), it avoids ballooning each object with separate properties for each method. On slower machines (or especially, slower JS interpreters) when many objects are being created this can mean a significant savings in time and memory.
And yes, new has one crucial disadvantage, ably described by other answers: if you forget to use it, your code will break without warning. Fortunately, that disadvantage is easily mitigated - simply add a bit of code to the function itself:
function foo()
{
// if user accidentally omits the new keyword, this will
// silently correct the problem...
if ( !(this instanceof foo) )
return new foo();
// constructor logic follows...
}
Now you can have the advantages of new without having to worry about problems caused by accidentally misuse.
John Resig goes into detail on this technique in his Simple "Class" Instantiation post, as well as including a means of building this behavior into your "classes" by default. Definitely worth a read... as is his upcoming book, Secrets of the JavaScript Ninja, which finds hidden gold in this and many other "harmful" features of the JavaScript language (the chapter on with is especially enlightening for those of us who initially dismissed this much-maligned feature as a gimmick).
A general-purpose sanity check
You could even add an assertion to the check if the thought of broken code silently working bothers you. Or, as some commented, use the check to introduce a runtime exception:
if ( !(this instanceof arguments.callee) )
throw new Error("Constructor called as a function");
Note that this snippet is able to avoid hard-coding the constructor function name, as unlike the previous example it has no need to actually instantiate the object - therefore, it can be copied into each target function without modification.
ES5 taketh away
As Sean McMillan, stephenbez and jrh noted, the use of arguments.callee is invalid in ES5's strict mode. So the above pattern will throw an error if you use it in that context.
ES6 and an entirely harmless new
ES6 introduces Classes to JavaScript - no, not in the weird Java-aping way that old-school Crockford did, but in spirit much more like the light-weight way he (and others) later adopted, taking the best parts of prototypal inheritance and baking common patterns into the language itself.
...and part of that includes a safe new:
class foo
{
constructor()
{
// constructor logic that will ONLY be hit
// if properly constructed via new
}
}
// bad invocation
foo(); // throws,
// Uncaught TypeError: class constructors must be invoked with 'new'
But what if you don't want to use the new sugar? What if you just want to update your perfectly fine old-style prototypal code with the sort of safety checks shown above such that they keep working in strict mode?
Well, as Nick Parsons notes, ES6 provides a handy check for that as well, in the form of new.target:
function foo()
{
if ( !(new.target) )
throw new Error("Constructor called as a function");
// constructor logic follows...
}
So whichever approach you choose, you can - with a bit of thought and good hygiene - use new without harm.
I have just read some parts of Crockford's book "JavaScript: The Good Parts". I get the feeling that he considers everything that ever has bitten him as harmful:
About switch fall through:
I never allow switch cases to fall
through to the next case. I once found
a bug in my code caused by an
unintended fall through immediately
after having made a vigorous speech
about why fall through was sometimes
useful. (page 97, ISBN
978-0-596-51774-8)
About ++ and --:
The ++ (increment) and -- (decrement)
operators have been known to
contribute to bad code by encouraging
excessive trickiness. They are second
only to faulty architecture in
enabling viruses and other security
menaces. (page 122)
About new:
If you forget to include the new
prefix when calling a constructor
function, then this will not be
bound to the new object. Sadly, this
will be bound to the global object, so
instead of augmenting your new object,
you will be clobbering global
variables. That is really bad. There
is no compile warning, and there is no
runtime warning. (page 49)
There are more, but I hope you get the picture.
My answer to your question: No, it's not harmful. but if you forget to use it when you should you could have some problems. If you are developing in a good environment you notice that.
In the 5th edition of ECMAScript there is support for strict mode. In strict mode, this is no longer bound to the global object, but to undefined.
JavaScript being a dynamic language, there are a zillion ways to mess up where another language would stop you.
Avoiding a fundamental language feature such as new on the basis that you might mess up is a bit like removing your shiny new shoes before walking through a minefield just in case you might get your shoes muddy.
I use a convention where function names begin with a lowercase letter and 'functions' that are actually class definitions begin with an uppercase letter. The result is a really quite compelling visual clue that the 'syntax' is wrong:
var o = MyClass(); // This is clearly wrong.
On top of this, good naming habits help. After all, functions do things and therefore there should be a verb in its name whereas classes represent objects and are nouns and adjectives without any verb.
var o = chair() // Executing chair is daft.
var o = createChair() // Makes sense.
It's interesting how Stack Overflow's syntax colouring has interpreted the code above.
I am newbie to JavaScript so maybe I am just not too experienced in providing a good view point to this. Yet I want to share my view on this "new" thing.
I have come from the C# world where using the keyword "new" is so natural that it is the factory design pattern that looks weird to me.
When I first code in JavaScript, I don't realize that there is the "new" keyword and code like the one in YUI pattern and it doesn't take me long to run into disaster. I lose track of what a particular line is supposed to be doing when looking back the code I've written. More chaotic is that my mind can't really transit between object instances boundaries when I am "dry-running" the code.
Then, I found the "new" keyword which, to me, "separates" things. With the new keyword, it creates things. Without the new keyword, I know I won't confuse it with creating things unless the function I am invoking gives me strong clues of that.
For instance, with var bar=foo(); I don’t have any clues as what bar could possibly be.... Is it a return value or is it a newly created object? But with var bar = new foo(); I know for sure bar is an object.
Another case for new is what I call Pooh Coding. Winnie-the-Pooh follows his tummy. I say go with the language you are using, not against it.
Chances are that the maintainers of the language will optimize the language for the idioms they try to encourage. If they put a new keyword into the language they probably think it makes sense to be clear when creating a new instance.
Code written following the language's intentions will increase in efficiency with each release. And code avoiding the key constructs of the language will suffer with time.
And this goes well beyond performance. I can't count the times I've heard (or said) "why the hell did they do that?" when finding strange looking code. It often turns out that at the time when the code was written there was some "good" reason for it. Following the Tao of the language is your best insurance for not having your code ridiculed some years from now.
I wrote a post on how to mitigate the problem of calling a constructor without the new keyword.
It's mostly didactic, but it shows how you can create constructors that work with or without new and doesn't require you to add boilerplate code to test this in every constructor.
Constructors without using "new"
Here's the gist of the technique:
/**
* Wraps the passed in constructor so it works with
* or without the new keyword
* #param {Function} realCtor The constructor function.
* Note that this is going to be wrapped
* and should not be used directly
*/
function ctor(realCtor) {
// This is going to be the actual constructor
return function wrapperCtor() {
var obj; // The object that will be created
if (this instanceof wrapperCtor) {
// Called with new
obj = this;
} else {
// Called without new. Create an empty object of the
// correct type without running that constructor
surrogateCtor.prototype = wrapperCtor.prototype;
obj = new surrogateCtor();
}
// Call the real constructor function
realCtor.apply(obj, arguments);
return obj;
}
function surrogateCtor() {}
}
Here's how to use it:
// Create our point constructor
Point = ctor(function(x, y) {
this.x = x;
this.y = y;
});
// This is good
var pt = new Point(20, 30);
// This is OK also
var pt2 = Point(20, 30);
The rationale behind not using the new keyword, is simple:
By not using it at all, you avoid the pitfall that comes with accidentally omitting it. The construction pattern that YUI uses, is an example of how you can avoid the new keyword altogether:
var foo = function () {
var pub = { };
return pub;
}
var bar = foo();
Alternatively, you could do this:
function foo() { }
var bar = new foo();
But by doing so you run risk of someone forgetting to use the new keyword, and the this operator being all FUBAR. As far as I know, there isn't any advantage to doing this (other than you being used to it).
At The End Of The Day: It's about being defensive. Can you use the new statement? Yes. Does it make your code more dangerous? Yes.
If you have ever written C++, it's akin to setting pointers to NULL after you delete them.
I think "new" adds clarity to the code. And clarity is worth everything. It is good to know there are pitfalls, but avoiding them by avoiding clarity doesn't seem like the way for me.
Case 1: new isn't required and should be avoided
var str = new String('asd'); // type: object
var str = String('asd'); // type: string
var num = new Number(12); // type: object
var num = Number(12); // type: number
Case 2: new is required, otherwise you'll get an error
new Date().getFullYear(); // correct, returns the current year, i.e. 2010
Date().getFullYear(); // invalid, returns an error
Here is the briefest summary I could make of the two strongest arguments for and against using the new operator:
Arguments against new
Functions designed to be
instantiated as objects using the
new operator can have disastrous
effects if they are incorrectly
invoked as normal functions. A
function's code in such a case will
be executed in the scope where the
function is called, instead of in
the scope of a local object as
intended. This can cause global
variables and properties to get
overwritten with disastrous
consequences.
Finally, writing function Func(),
and then calling Func.prototype
and adding stuff to it so that you
can call new Func() to construct
your object seems ugly to some
programmers, who would rather use
another style of object inheritance
for architectural and stylistic
reasons.
For more on this argument check out Douglas Crockford's great and concise book JavaScript: The Good Parts. In fact, check it out anyway.
Arguments in favor of new
Using the new operator along with
prototypal assignment is fast.
That stuff about accidentally
running a constructor function's
code in the global namespace can
easily be prevented if you always
include a bit of code in your
constructor functions to check to
see if they are being called
correctly, and, in the cases where
they aren't, handling the call
appropriately as desired.
See John Resig's post for a simple explanation of this technique, and for a generally deeper explanation of the inheritance model he advocates.
I agree with PEZ and some here.
It seems obvious to me that "new" is self descriptive object creation, where the YUI pattern Greg Dean describes is completely obscured.
The possibility someone could write var bar = foo; or var bar = baz(); where baz isn't an object creating method seems far more dangerous.
I think new is evil, not because if you forget to use it by mistake it might cause problems, but because it screws up the inheritance chain, making the language tougher to understand.
JavaScript is prototype-based object-oriented. Hence every object must be created from another object like so: var newObj=Object.create(oldObj). Here oldObj is called the prototype of newObj (hence "prototype-based"). This implies that if a property is not found in newObj then it will be searched in oldObj. newObj by default will thus be an empty object, but due to its prototype chain, it appears to have all the values of oldObj.
On the other hand, if you do var newObj=new oldObj(), the prototype of newObj is oldObj.prototype, which is unnecessarily difficult to understand.
The trick is to use
Object.create=function(proto){
var F = function(){};
F.prototype = proto;
var instance = new F();
return instance;
};
It is inside this function and it is only here that new should be used. After this, simply use the Object.create() method. The method resolves the prototype problem.
In my not-so-humble opinion, "new" is a flawed concept in 2021 JavaScript. It adds words where none are needed. It makes the return value of a function/constructor implicit and forces the use of this in the function/constructor. Adding noise to code is never a good thing.
// With new
function Point(x, y) {
this.x = x
this.y = y
}
let point = new Point(0, 0)
Vs.
// Without new
function Point(x, y) {
return { x, y }
}
let point = Point(0, 0)

Categories

Resources