Call class directly and not via instance variable - javascript

I have created the following two classes in my classes.js:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
display() {
console.log(this.firstName + " " + this.lastName);
}
}
module.exports = {
Person
};
As you can see I am exporting the two classes via module.exports.
Person = require('./classes.js');
const someone1 = new Person("First name", "Last name"); // <-- does NOT work
const someone = new Person.Person("First name", "Last name"); // does work
someone.display();
However, when calling the classes I get an error, when calling the class directly.
Any suggestions how to call the class directly?
I appreciate your replies!

If you want all your classes in one file called classes.js, then this should work;
// classes.js
class Person {
// ...
}
class Vehicle {
// ...
}
module.exports = {
Person,
Vehicle
}
// some-other-file.js
const { Person } = require('../classes')
const person = new Person('First', 'Last')
Although to keep things easy to understand, my recommendation would be to split your class into multiple files and then export each class from its file directly;
class Person {
// ...
}
module.exports = Person
const Person = require('../classes/person')
// do something

In this case you're exporting an object containing Person class
module.exports = {
Person
};
So when you import like Person = require('./classes.js')
You're actually importing the exported object. So Person after you've imported is similar to
Person = {
Person
};
You can either change the export by assigning the desired export object to module.exports like:
module.exports = Person
or change your import to use destructuring assignment to import like (notice the curly braces):
const { Person } = require('./classes.js');

If
module.exports = {
Person
};
therefore
Person = require('./classes.js').Person;
Alternatively, you can
module.exports = Person;
and
Person = require('./classes.js');

In classes.js you are exporting Person as an object property. So to make it work as you expect you can either do Destructuring Assignment
const { Person } = require('./classes')
Or just require class directly from classes.js file.
const Person = require('./classes').Person
Alternatively, and it's a better option, in my opinion, you can separate Person to its own file and export it by default.
File ./Person.js
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
display() {
console.log(this.firstName + " " + this.lastName);
}
}
module.exports = Person
And then in your main file just do:
const Person = require('./Person');

Related

How to define Singleton pattern with parameter using static keyword?

According to second answer from here, I'm trying to create Singleton pattern in JS for storing data and invoking its prototypes from the other instances.
A main problem is Singleton doesn't store the data after receives the first instance.
[{…}]
0: {firstName: "John", lastName: "Grand"}
This is how I've done:
export default class Terminal {
static cache(output) {
// Singleton
if (!Terminal.instance) {
Terminal.instance = new Terminal(output);
}
return Terminal.instance;
}
constructor(output) {
// Create an array
this.logs = [];
// Switch to an object
const data = Object.assign({}, output);
// Add the object to the array
this.logs.push(data);
// Inspect
console.log(this.logs);
}
}
// instance 1
import Terminal from './terminal.js';
class Person {
constructor(firstName, lastName, input) {
this.firstName = firstName;
this.lastName = lastName;
// Assign the Singleton
this.input = input || Terminal.cache(this);
}
}
let player1 = new Person('John', 'Grand');
// instance 2
import Terminal from './terminal.js';
class Grocery {
constructor(name, stock, input) {
this.name = name;
this.stock = stock;
// Assign the Singleton
this.input = input || Terminal.cache(this);
}
}
let shop1 = new Grocery('Apple', 12);
I want to let the new keyword inside of the class when I define the Singleton pattern.
Any tips to accomplish my problem?
Thanks.
The cache() method needs to push output onto the logs array when the object already exists.
static cache(output) {
// Singleton
if (!Terminal.instance) {
Terminal.instance = new Terminal(output);
} else {
Terminal.instance.logs.push(Object.assign({}, output));
}
return Terminal.instance;
}

Use the same instance through out the code javascript

Class Life {
constructor(name = 'no name') {
this.name = name;
}
getName() {
return this.name;
}
setName(name = 'no name') {
this.name = name;
}
}
const MyLife = new Life();
export { getName, setName } = MyLife;
export default MyLife;
How can I use the same instance of new Life() i.e, MyLife throughout my code?
Things I have tried;
const MyLife = new Life();
export const getName = MyLife.getName.bind(MyLife);
export const setName = MyLife.setName.bind(MyLife);
export default MyLife;
Every time I try to use this in another file i.e, myOther.js
import { setName } from '../path-of-class.js`
setName('Luke Skywalker'); // I get undefined.
What am I doing wrong here?
P.S: the class is in another library, I compile it with webpack & then use in another <package>, The class above works fine if used locally within the same <package> but when I try to use from <package-a> to <package-b> I get setName of undefined.
Try saving your instance of Life into a static variable probably near the class and return it with a static method
class Life {
static getInstance() {
if (!Life.instance) {
Life.instance = new Life();
}
return Life.instance;
}
constructor(name = 'no name') {
this.name = name;
}
getName() {
return this.name;
}
setName(name = 'no name') {
this.name = name;
}
}
Life.instance = null;
export default Life;
in another file:
import Life from 'module';
const myLife = Life.getInstance();
I'm not completely certain how webpack handles the imports. But having a single instance of a class and using it everywhere is a common pattern in object oriented programming (lookup singleton), usually solved by attaching a static variable of the instance to a class and getting it with a static method. This example achieves the same thing by having a static instance and using getInstance() to return it or create one if it wasn't already. This is a classic implementation of this pattern.

Recursively requiring modules in Node

So, let's say I have two classes, each of which requires the other:
Department.js:
const Person = require("./Person");
class Department{
constructor(id){
this.personel = getPersonel(id).map(person => new Person(person));
}
}
Person.js
const Department = require("./Department");
class Person {
constructor(id){
this.department = new Department(getDeptOfPerson(id));
}
}
const person = new Person(1);
const coworkers = person.department.personel;
Now, this doesn't work, and I can kinda understand why. It says "Person" is not a constructor at Department.js. However, if I put both classes in the same file, it works just fine.
So; my question is, how do I work around this? I'd really rather not keep both of these classes in the same file -- is there a better way?
I'm running the latest version of Node.
You can separate initializing objects from fetching data:
// types/Department.js
class Department {
constructor(id, personnel) {
this.id = id;
this.personnel = personnel;
}
}
// types/Person.js
class Person {
constructor(id, department) {
this.id = id;
this.department = department;
}
}
// findDepartment.js
const Department = require('./types/Department');
const Person = require('./types/Person');
function findDepartment(id) {
const personnel = getPersonnel(id).map(person => new Person(person));
return new Department(id, personnel);
}
// findPerson.js
const Department = require('./types/Department');
const Person = require('./types/Person');
function findPerson(id) {
const department = getDeptOfPerson(id);
return new Person(id, department);
}
These can even go back on the types (findDepartment.js → Department.js, Department.findDepartment = function (id) { …) if you really want.

How to add an method to a class in Javascript ES6

I need do add a method to a Javascript class using the new syntax. I tried this way:
class X{
constructor() {
this.a = 'b'
}
x(){
}
}
X.prototype.y = function (){
console.log('y')
}
var x = new X()
x.y()
console.log(X) // print the the class but not the new method.
It just prints:
class X{
constructor() {
this.a = 'b'
}
x(){}
}
But I expected
class X{
constructor() {
this.a = 'b'
}
x(){}
y(){
console.log('y');
}
}
How could I add a new method to a Javascript class?
this works fine, if you are checking this in google chrome console, then please check by expanding proto node.
or alternatively try checking
console.log(X.y)
or console.log(X.prototype.y)
or console.log(x.y)
this must print that function
There are two major ways to add methods to a class, this can be within the scope of the class when writing the code or using ".prototype" to attach a method to your class.
Below is an example of adding a method within the class scope:
class Person {
constructor(fName, lName) {
this.firstName = fName;
this.lastName = lName;
}
sayName = function() {
return `My Name is ${this.firstName} ${this.lastName}`
}
}
const firstPerson= new Person ("Thor", "Odinson")
console.log(firstPerson.sayName())
And below an example of a method creation from outside the scope of a class using a prototype:
class Person {
constructor(fName, lName) {
this.firstName = fName;
this.lastName = lName;
}
}
Person.prototype.sayName = function() {
return `My Name is ${this.firstName} ${this.lastName}`
}
const secondPerson= new Person ("Tony", "Stark")
console.log(secondPerson.sayName())
A very important thing to note is that using prototype to add a method to a class doesn't change the structure of the class. So logging the object won't render the method. But the method is available to all subclasses and instances of that class.
I know it's a bit late, but would this have solved your problem back then?
class XWithY extends X {
constructor() {
super()
}
y() {
console.log('y')
}
}
const xwy = new XWithY();
console.log(xwy instanceof X); // outputs true
You can use Object.setPrototypeOf.
Example:
// A class…
class Someone {
constructor(qui){
this.qui = qui
}
}
// A mixins with new methods
class MyMixins {
says(quoi){
console.log(this.qui + " says "+ quoi)
}
eats(quoi){
console.log(this.qui + " eats "+quoi)
}
}
// An instance…
const marion = new Someone("Marion")
// This fails…
//marion.says("hello!")
//marion.eats("potatoes")
//-----> Here's the trick <------
Object.setPrototypeOf(Someone.prototype, MyMixins.prototype);
// This pass…
marion.says("hello!") //=> "Marion says hello!"
marion.eats("potatoes") //=> "Marion eats potatoes"

How to properly export an ES6 class in Node 4?

I defined a class in a module:
"use strict";
var AspectTypeModule = function() {};
module.exports = AspectTypeModule;
var AspectType = class AspectType {
// ...
};
module.export.AspectType = AspectType;
But I get the following error message:
TypeError: Cannot set property 'AspectType' of undefined
at Object.<anonymous> (...\AspectType.js:30:26)
at Module._compile (module.js:434:26)
....
How should I export this class and use it in another module? I have seen other SO questions, but I get other error messages when I try to implement their solutions.
// person.js
'use strict';
module.exports = class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
display() {
console.log(this.firstName + " " + this.lastName);
}
}
// index.js
'use strict';
var Person = require('./person.js');
var someone = new Person("First name", "Last name");
someone.display();
If you are using ES6 in Node 4, you cannot use ES6 module syntax without a transpiler, but CommonJS modules (Node's standard modules) work the same.
module.export.AspectType
should be
module.exports.AspectType
hence the error message "Cannot set property 'AspectType' of undefined" because module.export === undefined.
Also, for
var AspectType = class AspectType {
// ...
};
can you just write
class AspectType {
// ...
}
and get essentially the same behavior.
With ECMAScript 2015 you can export and import multiple classes like this
class Person
{
constructor()
{
this.type = "Person";
}
}
class Animal{
constructor()
{
this.type = "Animal";
}
}
module.exports = {
Person,
Animal
};
then where you use them:
const { Animal, Person } = require("classes");
const animal = new Animal();
const person = new Person();
In case of name collisions, or you prefer other names you can rename them like this:
const { Animal : OtherAnimal, Person : OtherPerson} = require("./classes");
const animal = new OtherAnimal();
const person = new OtherPerson();
Use
// aspect-type.js
class AspectType {
}
export default AspectType;
Then to import it
// some-other-file.js
import AspectType from './aspect-type';
Read http://babeljs.io/docs/learn-es2015/#modules for more details
I simply write it this way
in the AspectType file:
class AspectType {
//blah blah
}
module.exports = AspectType;
and import it like this:
const AspectType = require('./AspectType');
var aspectType = new AspectType();
class expression can be used for simplicity.
// Foo.js
'use strict';
// export default class Foo {}
module.exports = class Foo {}
-
// main.js
'use strict';
const Foo = require('./Foo.js');
let Bar = new class extends Foo {
constructor() {
super();
this.name = 'bar';
}
}
console.log(Bar.name);
Several of the other answers come close, but honestly, I think you're better off going with the cleanest, simplest syntax. The OP requested a means of exporting a class in ES6 / ES2015. I don't think you can get much cleaner than this:
'use strict';
export default class ClassName {
constructor () {
}
}
I had the same problem.
What i found was i called my recieving object the same name as the class name. example:
const AspectType = new AspectType();
this screwed things up that way...
hope this helps
Sometimes I need to declare multiple classes in one file, or I want to export base classes and keep their names exported because of my JetBrains editor understands that better. I just use
global.MyClass = class MyClass { ... };
And somewhere else:
require('baseclasses.js');
class MySubclass extends MyClass() { ... }

Categories