Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript this.function vs return function?

Tags:

javascript

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?

like image 442
msmith1114 Avatar asked Oct 31 '25 05:10

msmith1114


1 Answers

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):

  1. 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.)
  2. 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 = ...
  3. 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.

like image 200
nnnnnn Avatar answered Nov 01 '25 20:11

nnnnnn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!