0

Hello i am trying to understand how objects are created in JS.Therefore i am trying to create the following class with plain JS.(I know i can't reinforce types) ,just placed them there as a reference.

Desired behaviour

class User{
    name:String;
    age:number;
    function StateCredentials(){
        return "Name:"+this.name+"\r\n"+"Age:"+this.age;
    }
}

I did not understand the order in which you attach the the prototype to the current object and when do you call apply on it.Also where should the instance method be placed.

Current Implementation

User=(function(age,name){
    function User(name,age){
        this.name=name;
        this.age=age;
        this.credentials=SetCredentials;
    }
    function StateCredentials(){
        return "Name:"+this.name+"\r\n"+"Age:"+this.age;
    }
    x={};
    x.__proto__= User.prototype; 
    User.apply(x,[a]); 
    return x;
});

Call:

function createObject(){
    u=User(3,3);
    u.StateCredentials();
}

Error: Uncaught TypeError: Cannot read property 'StateCredentials' of undefined

As a last note i have seen an implementation where an anonymous method is the trigger that encloses the constructor logic.

(function(){...})(arugments);
Bercovici Adrian
  • 8,794
  • 17
  • 73
  • 152
  • *"i am trying to understand how objects are created in JS."* To be clear: There are multiple ways to create objects, using `new Constructor()` is just one of them. The simplest is to use an object literal, `{...}`. Are you basically asking how `new` works? – Felix Kling Nov 08 '18 at 07:38
  • *"without OOP constructs"* What are OOP constructors for you? I feel like people have a different understand of what OOP means. JavaScript is all about objects. – Felix Kling Nov 08 '18 at 07:40
  • I was referring to how would you create an object if you would not have constructor `syntatic sugar`. I was expecting to be something similar to how you would do it in a language like `Clang`.And i was curious on how and where you attach the class method "pointers". – Bercovici Adrian Nov 08 '18 at 07:43
  • A constructor is really just a function that initializes an object. As I said, the simplest way to create an object is to use an object literal. Any function that creates and returns an object would be a constructor then. *"And i was curious on how you and where you attach the method "pointers"."* Assuming the methods/functions are predefined, all you need to do is `obj.method = method;`. – Felix Kling Nov 08 '18 at 07:46

3 Answers3

1

There are a couple of issues with your code:

  • The User function doesn't return anything. That's why u is undefined and you get that error. You'd have to add return x;
  • Even with that, the call u.StateCredentials(); would fail because you are never creating a property StateCredentials on x. The closest you are ding is creating the property credentials, so you could do u.credentials().
  • You still wouldn't see anything though because you are not doing anything with the return value. You could do console.log(u.credentials()).

Overall I'm not quite sure what you are trying to achieve. Ignoring that your class example is syntactically incorrect, classes are "plain JavaScript". The syntax is officially part of the language since 2015.

I feel like different people have a different understanding of what "OPP constructs" really are, so here are a couple of examples.

No class syntax (constructor function + prototype)

class is more or less just syntactic sugar. Under the hood we deal with normal constructor functions. So if you are asking how the equivalent pre-class syntax example looks like, it would be something like this:

function User(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.StateCredentials = function() {
 return "Name:"+this.name+"\r\n"+"Age:"+this.age;
}

var u = new User('foo', 42);
console.log(u.StateCredentials());

There is no need to actually instantiate the object yourself because new does that for you.


Our own new

If you are asking how to basically implement new yourself, then it would be something like this:

function User(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.StateCredentials = function() {
  return "Name:" + this.name + "\r\n" + "Age:" + this.age;
}

function newNew(constructor, ...args) {
  var instance = Object.create(constructor.prototype);
  var result = constructor.apply(instance, args);
  if (result && typeof result === 'object') {
     return result;
  }
  return instance;
}

var u = newNew(User, 'foo', 42);
console.log(u.StateCredentials());

Note: I'm using rest parameters (...args) for implicitly here, one could as well use arguments and slice it correctly.

  • Object.create(...) does the "magical" part of creating a new object with a specific value as it's protoype.
  • constructor.apply(...) simply calls the constructor with the new object set as its this value.
  • Then we either return the return value of the constructor if it is an object, or the object we just created.

No new

If you are asking how the equivalent would look like without new, constructor functions and this, then it would be something like this:

var UserPrototype = {
  StateCredentials: function() {
      return "Name:" + this.name + "\r\n" + "Age:" + this.age;
  },
};

function makeUser(name, age) {
  var instance = Object.create(UserPrototype);
  instance.name = name;
  instance.age = age;
  return instance;
}

var u = makeUser('foo', 42);
console.log(u.StateCredentials());

We still need Object.create to create a new object with a specific value as its prototype.


No prototypes

If you don't actually want to use prototypes, you can merge the objects using var instance = Object.assign({}, UserProtoype); instead or define and assign methods individually

function StateCredentials() {
  return "Name:" + this.name + "\r\n" + "Age:" + this.age;
}

function makeUser(name, age) {
  return {
    name: name,
    age: age,
    StateCredentials: StateCredentials,
  };
}

var u = makeUser('foo', 42);
console.log(u.StateCredentials());

And sure, StateCredentials could be defined inside makeUser. This is an optimization step so that we creating a new copy of that function every time makeUser is called.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • What is the difference between setting the `SetCredentials` to a `this` field inside the `constructor` (as i did) or setting it by attaching to the `User.prototype` property? Why should instance methods be set as `prototype` fields and fields not ? – Bercovici Adrian Nov 08 '18 at 07:33
  • 1
    See [Use of 'prototype' vs. 'this' in JavaScript?](https://stackoverflow.com/q/310870/218196) for a comprehensive answer on that one. – Felix Kling Nov 08 '18 at 07:35
  • The last part of your answer is what really solved my confusion.And how would you enclose all that logic inside one method?To behave "like a constructor".Can you place it all inside a `wrapper` ? – Bercovici Adrian Nov 08 '18 at 07:40
  • 1
    `makeUser` is basically a constructor... not sure what else you want. That `UserPrototype` is defined inside the function? Then we would create a new copy of the object and function every time `makeUser` is called, which works but is unnecessary. – Felix Kling Nov 08 '18 at 07:43
  • I added another example that doesn't use prototypes though there isn't a huge difference. – Felix Kling Nov 08 '18 at 07:46
1

Or you could use class for newer browsers

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  StateCredentials() {
    return "Name:"+this.name+"\r\n"+"Age:"+this.age;
  }
}

let u = new User('name', 31);

console.log(u.StateCredentials());
Yoannes Geissler
  • 791
  • 1
  • 9
  • 18
  • Thank you for your suggestions.However i wanted to know how it translates at the lowest level. – Bercovici Adrian Nov 08 '18 at 07:35
  • 1
    @BercoviciAdrian: *"However i wanted to know how it translates at the lowest level."* You essentially want to know how `new` works then. See the second example in my answer. – Felix Kling Nov 08 '18 at 07:37
0

You're making this a lot more complicated than it has to be:

function user(age,name){
  this.name=name;
  this.age=age;
}

user.prototype.StateCredentials = function(){
  return "Name:"+this.name+"\r\n"+"Age:"+this.age;
}

var u = new user(12, "Little Billy");
console.log(u.StateCredentials());
var v = new user(11, "Little Suzy");
console.log(v.StateCredentials());

Prototype is attached with the new keyword. apply isn't used in this scenario, though you would occasionally see it in a constructor function for certain types of inheritance.

Andrew Ridgway
  • 574
  • 2
  • 9