Im a bit confused learning all the new ES6 vs ES5 syntax with javascript and when it comes to functions/classes with methods and calling upon those methods I can't really tell what is the "right way".
For example take this code:
function account(amount) {
let cash = amount;
this.setCash = function(amt)
{
cash = amt;
}
this.getCash = function()
{
return cash;
}
}
var person = new account(100);
console.log(person.getCash()); //returns 100
person.setCash(150);
console.log(person.getCash()); //returns 150
Works like normal as expected (This is how I originally saw the methods being used when going through tutorials).
However i've seen this occasionally:
function account2(amount) {
let cash = amount;
function setCash(amt)
{
cash = amt;
}
function getCash()
{
return cash;
}
return{
getCash,
setCash
}
}
var person2 = new account2(50);
console.log(person2.getCash()); //returns 50
person2.setCash(175);
console.log(person2.getCash()); //returns 175
Both of these work perfectly fine, and do as I think they should. However is one just an older way of doing it? or less correct maybe? This is my biggest barrier in learning JS right now, since ES6 is here there are so many different ways to do something as simple as making a "class" in JS with methods.
Personally the first way seems easier since you don't have to return the functions....but for example at work I see the 2nd way used mostly?
If you removed new from the second version (more on that in a moment) then both of your examples are perfectly fine ways of creating an object with private data accessed via public get/set methods. Which one you would choose is personal preference, or dependent on whether you want to extend the functionality further with prototype methods, etc.
The reason I suggest removing new from the second version is that although both examples work, the first is a "normal" use of the new operator, but the second is an "incorrect" use of the new operator - not a syntax error, just semantically incorrect and potentially misleading for other people reading your code.
So why is that second use of new semantically incorrect? When you say var person = new account(100):
A new object is created with a prototype that is account.prototype. That means the new object inherits any methods and properties of the account.prototype, and from its prototype, etc. (In your case you haven't defined any methods on the prototype, but you could.)
Within the account() function, this will refer to the object created in step 1. Which is why you can attach methods to it with this.setCash = ...
The new object is returned from account() by default. This step will not occur if there is an explicit return statement returning something else as in your account2() function.
So in the first example, person instanceof account is true, because the default object was returned. In the second example, person2 instanceof account2 is false, because a different object was returned - this is misleading for people reading your code, because when they see person2 = new account2() they might reasonably expect that person2 will be an instance of account2 but it's not. It's also a bit inefficient, because the JS engine goes to the trouble of creating an object for you and then you don't use it.
So the second example would be more "correct" without new, providing the same behaviour minus the unnecessary auto object creation:
var person2 = account2(50);
(Almost) any JS function that you write can be called with new, but there is a convention that we describe functions intended to be called with new as "constructors", and usually the function name is capitalised, so Account(), not account(). (The spelling doesn't change the behaviour, it's just an extra hint for people reading the code.)
Note that use of new isn't the only way to link objects to particular prototypes: it is the old-school-but-still-perfectly-valid way, but you can use Object.create() instead.
By the way, the behaviour in question is not new in ES5 or 6, though let and the shortcut object literal syntax in account2 are new.
When you create an instance with new keyword this is returned implicitly where as when assign a function to a variable without new, you need to use return explicitly.
Something I have always wondered about, how does javascript (or languages in general) use an 'alternate' syntax for declaring instantiations of built in objects? for example.
// This being the same as..
var array = new Array('hi','there');
// This.
var array = ['hi','there'];
// or
var myFun = new Function("a","b","return a * b");
// being the same as..
var myFun = function(a,b){ return a * b }
Is there any way I can do this if I were to work on my own library? say I wanted to make some kind new syntax for a particular thing? Is there something in the prototype method? Or is this something that is beyond the capture of the developer and only within the grasp of the W3?
John Resig's jQuery seems to have a unique syntax
$('.class').css({'color':'#000'});
Is there something a bit deeper he had to do in order to get this level of customization? or was it a matter of doing things like..
// Obviously just a very simple example.
var $ = function(param){
return document.querySelectorAll(param);
}
I would be very interested to know and look forward to hearing your answers, thank you.
No JavaScript library alters the syntax of the language, as JavaScript has no native facilities to do that. For example, jQuery "syntax" is just simple JavaScript syntax. You too can create your own function named $, and write functions that return objects to allow that "chaining" code style.
Some languages have varyingly-powerful macro facilities that effectively do allow new syntax to be concocted. JavaScript isn't one of those languages (without some external tool).
Things like TypeScript, PureScript, and CoffeeScript are essentially pre-processors that parse a different syntax to generate plain JavaScript.
Before I begin, I want to confess that I am a JavaScript novice and I have very little understanding/knowledge of JavaScript patterns and terminologies so please feel free to explain basic concepts to me like I'm 5!
I have previously used the JavaScript prototype pattern to great effect in my work.
Here is a sample of my previous work with the prototype pattern
var SomeNameSpace = SomeNameSpace || {};
SomeNameSpace.SomeClass = function(oSomeParameter){
this.SomeProperty = oSomeParameter
...
}
SomeNameSpace.SomeClass.prototype = {
SomeClassMethod: function (oSomeOtherParameter) {//code here}
}
var someClassInstance = new SomeNameSpace.SomeClass("some string");
var result = someClassInstance.SomeClassMethod("some other string");
That snippet is an example of how I have always worked with javascript
I have been put in charge of supporting some new javascript code. I would like to introduce the same sort of prototype pattern to this new library. However, the namespace is written in a way which is foreign to me and I do not know how to modify it to suit my needs.
An example
if (typeof SomeNamespace == "undefined") {
SomeNamespace = { __namespace: true };
}
SomeNamespace.SomeOtherNamespace = {
SomeClass: function(oSomeParameter){
this.SomeProperty = oSomeParameter
...
}
}
I don't know how to add prototype functions to this code....
(Sorry if I'm vague on details, I'm not even sure why the namespace is declared like that in my 2nd example so if someone could explain that to me, that'd be great!)
*Edit*
Corrected syntax in 2nd example
*Edit*
Left out the "new" keyword in my example
Defining methods
This piece of code is not syntactically correct:
SomeNamespace.SomeOtherNamespace = {
SomeClass = function(oSomeParameter){ // you probably have : instead of =
this.SomeProperty = oSomeParameter
...
}
}
To add an instance method in the second example, you can simply do after the definition of SomeClass:
SomeNamespace.SomeotherNamespace.SomeClass.prototype.SomeClassMethod = function() {
};
In both the first and the second way you mentioned, your code wants to show that these functions (instance methods in first example, classes in second example) all belong to the same object (prototype in first example, namespace in second example). That is all nice and good for a few properties, but i find this gets more in the way when you're dealing with classes with many methods or even worse, namespaces with many classes.
I would recomend you separate your code using different files and minify them together. A folder represents a namespace and a file represents a class. Follow the pattern in your first example, but instead of saying "this is the prototype object with these methods", simply add them one at a time using the example line above.
Declaring namespaces
First of all, we need to be on the same page. In JavaScript a namespace is simply an object (that contains as properties whatever interests you, constructors, static functions - ex factory methods, other namespaces, etc).
The first example a = a || {} makes sure that namespace a is defined but makes sure not to overwrite it if it was defined elsewhere. For most use cases it is enough and it has the advantage of being very concise and clear to most people reading your code.
The second example does something similar to what the first does, but with two differences:
Specifically checks that a was undefined before defining it (ex1 only checked for falsyness which is usually enough)
Adds the _namespace property to a
Regarding the check for undefined, i doubt you need it. If your code has collisions with something that uses 'a' as something else than an object, then there's a high chance something will break regardless of the method used.
The _namespace property is something purely conventional to that code i think. It may help with various tools (perhaps during debugging or for automatic documentation generation), but that's about all i can think of. Obviously you're in a much better position to see if it is actually used for something, so if you encounter an interesting usage, perhaps you could leave a comment.
To sum it up, i prefer the first variant because it is more concise and even more frequent (so easier to recognize by someone reading the code).
Full example:
// class definition
a = a || {}; // global namespace, all good
a.b = a.b || {}; // both lines are needed
a.b.Class = function() {
this.myProp = 'hello';
};
a.b.Class.prototype.myMethod = function() {
};
// usage
var myInstance = new a.b.Class();
instance.myMethod();
var x = instance.myProp;
I'm pretty new to Javascript, as my SO profile will attest.
I've just been reading up on a few tutorials and come across something I don't totally understand in regards to Object Orientation and Encapsulation when applied with Javascript.
The tutorial stated that Javascript objects can be declared like this:
var myCustomObject = new Object();
And that you can give it instance variables like this:
myCustomObject.myVariable = "some value";
myCustomObject.myOtherVariable = "deadbeef";
Finally, it states that you can create a template function to create new objects like this:
function CustomObject(myVariable, myOtherVariable)
{
this.myVariable = myVariable;
this.myOtherVariable = myOtherVariable;
}
I also know that you can create and assign values to variables that do not yet exist and as a result are declared implicitly, as is seen in the example, where myCustomObject didn't have a myVariable, but now it does.
So, my question is: What is there to prevent new variables from being added at some other point in the code. If I'm trying to learn how an object works and what I can/should do with it, I may never see the variable additions that could well be in some other .js file, and thus not have a full understanding of the object...
Also, how do I know that some object that has just been created won't suddently turn out to have 60 more variables added later on in code that weren't mentioned at all at creation time?
How are you meant to be able to understand what an object can contain at a glance if more can just be added to it "willy nilly"?
I can't quite believe that I'm about to quote Spiderman but …
With great power comes great responsibility
JavaScript is powerful and flexible and gives programmers lots of freedom. It doesn't come with features designed to stop programmers writing bad code. When you write JavaScript, you are responsible for making sure the code is good, not the language.
You can't, there's nothing that stops me from doing whatever I want with your objects ;) However, you don't have to use those variables..
One thing you can do is to play with scopes, example:
function myConstructor()
{
var myState = {}; //Create new, empty object
myState.text = "Hello World!";
this.say = function() {
alert(myState.text);
};
}
In this simple example you can store you internal variables in myState (or "var text = '';" etc) and they aren't accessible from outside since they are not members of an object, they are just private variables in your function. And, as you can see, the function say still has access to it.
Short answer: Absolutely nothing.
Long answer:
Javascript is a dynamic language in more ways than just the type system. Every object like thing in the language is basically an associative array which can be added to as you please. Variables (which can obviously contain these object like things) exist only within their function scope.
You can use this point to simulate private members which can tame the situation somewhat. I've posted examples of this several times before so I'll just refer you to the definitive guide on the subject: http://javascript.crockford.com/private.html.
As far as adding new members to objects in a way you did not intend goes, there's really nothing to be done that's just the way the language is.
Afterthought:
When approaching javascript try to remember it's really not an OOP language it's a weird and wonderful mix of functional / prototypical with a few OOP ideas. Don't be fooled by the java like syntax, you'll have a much better time if you play to the languages strengths rather than ape java.
Javascript objects are transformers (TM), they can turn from one form to another.
In practise this only happens to enrich objects, never to cause harm. It allows one to for example upgrade an existing 'class' rather then subclassing or to decorate instances again removing the need to create even more 'classes'. Take the following example:
var Vehicle = function(){}
var factory = {
create: function(name, props){
var v = new Vehicle();
v.type = name;
for(var prop in props) {
v[prop] = props[prop];
}
}
}
var bike = factory.create('Bike', {
wheels: 2
});
var car = factory.create('Car', {
wheels: 4,
doors: 5,
gear: 'automatic'
});
var plane = factory.create('Airplane', {
wings: 2,
engines: 4
});
Imagine what the code above would take without dynamic objects and you couldn't do this:
// lets paint our car
car.color = 'candy red';
// bling!
car.racingStripes = true;
car.mirrorDice = true;
car.furryChairs = true;
You get to enrich/personalize objects in a much easier way.
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)