First of all, no, I'm not trying to create any sort of Java-like interface for my JavaScript code. I've seen those questions all over, and while I'm still a relative novice to JavaScript, I know those aren't part of the language.
However, I'm curious what the actual intended use of the interface keyword is. For example, Math is an interface, containing definitions (but not implementations). I believe (and may be totally wrong) that these are there to provide a means for the definers of the language to enforce a set of behaviors to be implemented in various JavaScript engines. Is that correct?
Furthermore, I have a desire to have a "static class" that contains a bunch of utility methods. I like that Math.sqrt(3) has an outer namespace ('Math') which is capitalized, and a number of logically similar methods and values in it. Maybe it's just my Java/Ruby background that makes me want a capital on the grouping objects. Is that bad form?
var ShapeInspections = {
isSymmetrical: function (s) {
// determine if shape is symmetrical
},
numAngles: function (s) {
// return the number of angles
}
}
A purely contrived example, but is it anti-idiomatic to name the "module" this way?
Okay, so as with other answers, you know that the keyword interface has no real use case in Javascript world, yet.
Your Math example made me suspicous that you are talking about a design pattern, called Module Pattern, widely used for scoping Javascript code. There are many ways of making your code modular. For example just like OddDev answered you , the famous Prototype Pattern can embed your code in a modular fashion (just like your Math example). Here is the Revealing Prototype Pattern example with also private variables and functions for additional flexibility:
/* Example from:
http://www.innoarchitech.com/scalable-maintainable-javascript-modules */
var myPrototypeModule = (function (){
var privateVar = "Alex Castrounis",
count = 0;
function PrototypeModule(name){
this.name = name;
}
function privateFunction() {
console.log( "Name:" + privateVar );
count++;
}
PrototypeModule.prototype.setName = function(strName){
this.name = strName;
};
PrototypeModule.prototype.getName = function(){
privateFunction();
};
return PrototypeModule;
})();
but that is not all. Other options include Scoped module pattern, POJO module pattern and many more. Have a look at How to Write Highly Scalable and Maintainable JavaScript: Modules, it has a very simple and yet thorough set of examples.
So far, we talked about plain Javascript. If you have the ability to use libraries in your code, then amazing set of libraries such as Requirejs, CommonsJS are there to help you on this with out-of-the-box functionalities. Have a look at Addy Osmani's post about Writing Modular JavaScript With AMD, CommonJS & ES Harmony.
The interface keyword in javascript is a FutureReservedWord, so it does absolutely nothing right now, though that may change in the future specifications. (See ECMAScript 5.1, section 7.6.1.2). In the ES6 draft, this is also the same.
As for you module, this is a perfectly idiomatic solution. It is always a good idea to "namespace" your functions, as it keeps the global scope as clean as possible.
I believe (and may be totally wrong) that these are there to provide a means for the definers of the language to enforce a set of behaviors to be implemented in various JS engines. Is that correct?
No, this is not correct. Things like "Math" etc. are objects containing functions. If you use for eyample "Math.pow(...)" you just execute the function stored in the "Math" object. Check this example:
var Math = {};
Math.prototype.pow = function(){
alert("stuff");
}
var ShapeInspections = { isSymmetrical: function (s) {
// determine if shape is symmetrical }, numAngles: function (s) {
// return the number of angles } } A purely contrived example, but is it anti-idomatic to name the "module" this way?
It's okay to name your objects like this. As already discussed "Math" is also just an object and follows these naming conventions.
To make things clear for the interface keyword:
The following tokens are also considered to be FutureReservedWords
when they occur within strict mode code (see 10.1.1). The occurrence
of any of these tokens within strict mode code in any context where
the occurrence of a FutureReservedWord would produce an error must
also produce an equivalent error:
implements let private public yield
interface package protected static
It's just reserved cause it's "may" needed in the future. So don't worry too much about it :) http://www.ecma-international.org/ecma-262/5.1/#sec-7.6
Do not confuse the "interfaces" that are specified in IDL with the interface keyword.
The latter is reserved for potential future use, but is not yet actually used in ECMAScript (not even in ES6).
Related
I'm writing a library that I hope to be compatible with Closure Compiler in Advanced mode. Most objects in the library maintain an internal object of attributes that are frequently part of the API, which leads to my source files being filled with lots and lots of functions like this.
/*
* Get name.
*/
Layer.prototype.getName = function() {
return this.attrs.name;
}
/*
* Set name.
*/
Layer.prototype.setName = function(name) {
this.attrs.name = name;
}
I can think of a billion ways to optimize this to declutter my code a bit. One example: KineticJS, as per this related question, does something a bit like this:
Global.addGettersSetters = function(obj, property) {
obj['get'+property] = function() { return this.attrs[property] }
obj['set'+property] = function(val) { this.attrs[property] = val }
}
// Later that day, in our original object, we have:
Global.addGettersSetters(Layer, 'name');
My understanding is that this is a no-no with Closure Compiler--the names won't be shortened and the functions won't be optimized because I'm specifying the properties of Layer as strings.
So, is there a way for me to fully and properly define the interface without cluttering up my code? Something in the Closure Library I've overlooked, perhaps?
An alternative solution: is there a way to do C#-style properties in modern JS? In a way Closure Compiler finds permissible? I have the luxury of targeting Webkit and only Webkit with this library, so stuff that's not yet fully implemented is fine.
If the getters/setters are public anyway, then you need them to not be renamed in the minified js. That means having them use strings for names is fine - they won't be minified but that's what you wanted.
Yes, modern JS has getters/setters.
You cannot dynamically add a function which could then be compiled (and minified/obfuscated) by the Closure Compiler because that dynamic "addGettersSetters" function would only be used at runtime, so the compiler has no knowledge of what it could be creating. The downside of using the compiler is a lot of duplicate pre-compiled code, but the benefit is that the majority of the places where your getters and setters are used will either be minified or just changed to inline references to the variables.
Also, by putting in explicit getters/setters and properly annotating them with JsDoc annotations:
/*
* Set name.
* #param {string} name
*/
Layer.prototype.setName = function(name) {
this.attrs.name = name;
}
you can add some level of type safety to your code to ensure you get a warning during compilation if someone calls "setName(5)".
Otherwise I would follow Chris's suggestion and look into JS getters / setters (other reference here). I have not used these with the closure compiler though so I cannot vouch for them.
Sorry, I don't get the ne8il answer and why it was marked as the correct one.
You can do what you want by just adding .prototype between obj and [ like this:
function addGettersSetters(obj, property) {
// You can also add this if you don't want to declare attrs = {} each time
// if (!("attrs" in obj.prototype)) obj.prototype.attrs = {};
obj.prototype['get'+property] = function() { return this.attrs[property] }
obj.prototype['set'+property] = function(val) { this.attrs[property] = val }
}
And also writing the property name with capital letter. Then you can use it like this:
var Layer = function() { this.attrs = {}; };
// Or just: 'var Layer = function(){};' if you use the line commented above
addGettersSetters(Layer, 'Name');
var layer = new Layer();
layer.setName("John");
alert(layer.getName()); // "John"
Not a complete answer of the original question, just adding some info.
You can see how various JavaScript OOP frameworks handle getters/setters e.g. here: jsPerf.com - JavaScript Object Oriented Libraries Benchmark with getters and setters
is there a way for me to fully and properly define the interface without cluttering up my code?
Tan Nhu (original author of the benchmark) created his own OOP library jsface which is available at: https://github.com/tnhu/jsface
I like it, I use it for exactly this reason
EDIT: how are the getters/setters generator solved in TypeScript is mentioned e.g. in SO article get and set in TypeScript
For more complete list of other frameworks and their way of encoding getters/setters you can check List of languages that compile to JS · jashkenas/coffeescript Wiki · GitHub
ok so i know that prototype is used for inheritance and when coupled with a constructor function can be used to make custom methods. so my question here is two fold: how do i make methods for pre-built JavaScript objects like integers,strings,arrays,etc...
the other question is besides making my own methods what is the usefulness of constructors/prototype in everyday web development(i.e. creating websites) or is this more so for high-end development like making a web app or developing with new tech(i.e. html5 canvas or three.js) i haven't seen an example anywhere on the web of this being used in an everyday situation.
To create a Javascript method to an already existing object, you can simple add it to its constructor's prototype:
String.prototype.firstLetter = function() { return this.charAt(0); }
var myStr = "Cool str!";
alert(myStr.firstLetter()); // 'C'
As for how useful it will be, depends on what you do with Javascript. If you write client-side code and you need to modify an existing component, monkey-patching a function may be useful there. If you need some structure on your code (and you do), creating an object to represent the interface state may be useful.
Also, knowing how to use a tool usually avoids self-harm. =)
If you are interested, you may want to take a look into Crockford's page or buy his Javascript: The Good Parts book.
There is a lot of confusion you can avoid if you get to know the language, and you may even get to like it and find out you can do a lot of useful stuff in it.
Here's an example that extends Number:
Number.prototype.between = function(a, b) {
return this >= a && this <= b
}
var num = 0;
if (num.between(0,0)) alert('is between')
else alert('not');
Although I often use the prototype, I have not yet run across a good reason to use the constuctor property, which returns the type of an Object. W3schools.com has a good illustration of this property at http://www.w3schools.com/jsref/jsref_constructor_math.asp
You can add functions into a class's prototype:
String.prototype.report_fish = function() { alert("a fish!"); };
"".report_fish();
You can do this with numbers as well, although the syntax to invoke is slightly different:
Number.prototype.report_fish = function() { alert("a fish!"); };
(0).report_fish();
As to why you'd do this, I personally believe that you should avoid doing this to built-in objects where possible. (A persistent problem to work around when building re-usable Javascript libraries used to be and probably still is people's tendency to override and extend the Object prototype.)
Does anyone know if structuring javascript will be changed? What I mean is to have a way to manage javascript classes into packages, like in Java. Is there already a way?
I guess you are familiar with the Java concept of naming packages after a domain you own, this way avoiding collision with the packages of other vendors. You can simulate Java packages (and avoid possible naemspace collisions) with:
if (typeof(org) == "undefined")
org = {};
if (typeof(org.mydomain) == "undefined")
org.mydomain = {};
if (typeof(org.mydomain.mypackage) == "undefined")
org.mydomain.mypackage = {};
org.mydomain.mypackage.MyClass = function (newA) {
// constructor
this.a = newA;
}
org.mydomain.mypackage.MyClass.staticMethod = function () {
// static method
return "static";
}
org.mydomain.mypackage.MyClass.prototype.method = function () {
// normal method
return a;
}
var o = new org.mydomain.mypackage.MyClass(13);
console.log(o.method());
console.log(org.mydomain.mypackage.MyClass.staticMethod());
You can even simulate Java's import if you are working in a limited scope. (Doing this in the global scope would eliminate the whole point of packaging):
function afunc() {
var MyClass = org.mydomain.mypackage.MyClass;
var o = new MyClass(33);
console.log(o.method());
console.log(MyClass.staticMethod());
}
The weakest link here is the root of our namespace, org (or com or any top level domain). An other class may use it for some other reasons. Using org_mydomain as the root instead of org.mydomain may give some safety.
Edit:
You have other possibilities for the root name too if you want to avoid using TLD as the root. If your domain name is unique enough (for example a hip misspelled one like foogz.com) you can assume that there will be no other company writing reusable JavaScript classes who will go for foogz.org or foogz.biz, so probably you will be the only foogz out there. :)
An other possibility is to append your TLD to the domain name and use that for the first tag for example: mydomainorg.packagename.ClassName.
There are no JavaScript classes. There are only Objects. You can pack a bunch of objects into a different object, and treat it like a module/namespace if you wish. (example at the end.)
Because of that, there can't be any "improvements" in the field of JavaScript classes because there aren't any, and I hope there won't ever be either. And frankly, that's for the best. Would you rather deal with insane getters/setters, static members, protected, type coercion and so on etc? Prototypal inheritance beats "Classical inheritance" by miles. It's just that JavaScript didn't have too much time to get it just right.
For amazing explanations on how JavaScript objects work, I recommend Douglas Crockfords' "On JavaScript", or some answers from our very own members.
An example of "namespacing":
var obj = {
classRoom : {...},
objectify : function() {...},
capacity : 5
};
var myClass = obj.classRoom; //access it like you access a module
var capacity = 7; //this is a global variable named capacity, so it won't tamper with obj.capacity
Check out http://joose.it, it has a great module system (library, not language extension). The 4th edition of the ECMA-262 spec has packages, and it's implemented in actionscript.
There is some speculation (e.g. by John Resig) about new features like object freezing and packages that might be added to ECMAScript Harmony (a.k.a 6th Edition).
However, I personally doubt that the language committee would consider such a drastic change to the way the language handles some of its core OO principles.
JavaScript is dynamic code in a file. All you do is load some source code and run it dynamically.
Every structuring and managing system is dynamically written and done at runtime. There are lots of ways you can manage and structure javascript code.
requirejs check define
yui check YUI.add
dojo check dojo.provide
and more
Personally I recommend requireJS as it's not tied into any framework / other libraries.
I am in the process of refactoring my code. I'm having trouble deciding on how exactly to implement a couple utility functions I have. Specifically, if certain functions are better off in my personal namespace or extending js Objects directly.
Example of extending native JavaScript Objects
(is this the proper term?).
String.prototype.prettyDate = function(){
return (this.substr(5,2) + '/' + this.substr(8) + '/' + this.substr(0,4));
}
var myString = "2010-12-27";
//logs 12/27/2010
console.log(myString.prettyDate);
Example using my own namespace
var myNamespace = (function(){
var my = {};
my.prettyDate = function ( dateStr ){
return (dateStr.substr(5,2) + '/' + dateStr.substr(8) + '/' + dateStr.substr(0,4));
}
return my;
}());
var pretifiedDate = myNamespace.prettyDate('2010-12-27');
//logs 12/27/2010
console.log(pretifiedDate);
Questions to consider
When is a utility justifiably inserted into a native JavaScript Object?
How can I tell when a utility is better off being in my own namespace?
Almost never, because of:
a/ possible conflicts with other libraries
b/ extended functions are iterated as properties by in operator, which poses problems unless filtered out by hasOwnProperty (which is not commonly used)
You can justify this for small, one-script works, but only if you 200% sure that no one, never ever will try to reuse that code somewhere. In such case use it only for functionality which spans more than one module of your code. Extending String with trim() - ok, extending String with prettyDate() - doubtful, extending Object with displayAsPageHeader() - scary.
So, almost always.
Watch this video:
http://ejohn.org/blog/building-a-javascript-library/
John Resig reckons that extending native objects is a recipe for disaster, particularly when a framework or application is likely to grow into something that does far more than was initially intended.
Unfortunately, this question doesn't have a "right" answer. It's a good discussion to have but I fear it'll be closed here. Whether native objects should be extended at all is a subjective debate, and if you accept that it's conditionally okay the answer to "when?" is "depends."
If you have control over its use and whether it will collide with other code, there's really no reason you shouldn't. It can be quite convenient and may reduce code size significantly.
Where there's a real problem with extending native objects is when you have other code running alongside your extension, which may be expecting a different extension in with the same property name, or which may be carelessly using for(var i in obj) without guarding against extensions up the prototype chain.
Ok... i'm not expert at this, but almost never!
Things you do are safer inside your namespace. And everything works fine if you follow the module pattern http://www.yuiblog.com/blog/2007/06/12/module-pattern/
However theres are some little tricks that allows us to avoid to overwrite others namespace. per example:
var myNamespace = {}; //my namespace, unsafely written
//Better solution
if(typeof myNamespace === 'undefined'){
var myNamespace = {};
}
//Shorter solution
var myNamespace = myNamespace || {};
It depends on how much control you have over what code is being run/loaded:
If it's all under your control there's nothing wrong with extending built-in objects, JavaScript is designed to be able to do this. The only problem with this is that you can have unexpected issues when two libraries change the same something. Luckily you wouldn't do this to yourself, right?
If you don't/can't know, a namespace is much safer albeit clunky and verbose. This is always safer.
Personally, I prefer the second option because I dislike overly verbose code and namespaces look funny.
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)