5

In PHP , I've used traits before which is a nice way of separating out reusable code & generally making things more readable.

Here is a specific Example: ( trait and class can be in separate files ) . How could I do this in nodejs?

<?php

trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
    ..more functions..
}

class TheWorld {
    use HelloWorld;
}

$o = new TheWorldIsNotEnough();
$o->sayHello();

?>

In Nodejs , I have looked at at Stampit which looks quite popular , but surely there is a simple way to compose functions in a nice OOP & make more readable in nodejs without depending on a package?

Thanks for your time!

ponury-kostek
  • 7,824
  • 4
  • 23
  • 31
Martin Thompson
  • 3,415
  • 10
  • 38
  • 62
  • This question is not narrow enough to be on-topic for Stack Overflow. The idea here is to help with a specific problem with a specific bit of code, not to give general advice on broader approach issues or to recommend libraries, as these things tend to be opinion-based more than anything else. – Tomalak May 15 '18 at 06:58
  • Thanks @Tomalak . I have edited & given a specifc example. – Martin Thompson May 15 '18 at 09:31
  • What you show here can be implemented quite easily with JS' prototype inheritance. Create an object that has all the methods you want, make that object the prototype of another object, and the other object will gain all those methods. There are many posts that explain prototype inheritance, here on the site ([example](https://stackoverflow.com/q/19633762)) and elsewhere (like [MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance)). I encourage you to read up on the topic. – Tomalak May 15 '18 at 09:49

2 Answers2

14

In JavaScript you can use any function as trait method

function sayHello() {
  console.log("Hello " + this.me + "!");
}

class TheWorld {
  constructor() {
    this.me = 'world';
  }
}

TheWorld.prototype.sayHello = sayHello;
var o = new TheWorld();
o.sayHello();

or pure prototype version

//trait
function sayHello() {
  console.log("Hello " + this.me + "!");
}

function TheWorld() {
  this.me = "world";
}

TheWorld.prototype.sayHello = sayHello;
var o = new TheWorld();
o.sayHello();

You can even create function that's apply traits to class

//trait object
var trait = {
  sayHello: function () {
    console.log("Hello " + this.me + "!");
  },
  sayBye: function () {
    console.log("Bye " + this.me + "!");
  }
};

function applyTrait(destClass, trait) {
  Object.keys(trait).forEach(function (name) {
    destClass.prototype[name] = trait[name];
  });
}

function TheWorld() {
  this.me = "world";
}

applyTrait(TheWorld, trait);
// or simply
Object.assign(TheWorld.prototype, trait);
var o = new TheWorld();
o.sayHello();
o.sayBye();
ponury-kostek
  • 7,824
  • 4
  • 23
  • 31
0

There is the NPM module: https://www.npmjs.com/package/traits.js

Code example from their README:

var EnumerableTrait = Trait({
  each: Trait.required, // should be provided by the composite
  map: function(fun) { var r = []; this.each(function (e) { r.push(fun(e)); }); return r; },
  inject: function(init, accum) { var r = init; this.each(function (e) { r = accum(r,e); }); return r; },
  ...
});

function Range(from, to) {
  return Trait.create(
    Object.prototype,
    Trait.compose(
      EnumerableTrait,
      Trait({
        each: function(fun) { for (var i = from; i < to; i++) { fun(i); } }
      })));
}

var r = Range(0,5);
r.inject(0,function(a,b){return a+b;}); // 10
Vasyl Boroviak
  • 5,959
  • 5
  • 51
  • 70