What is causing ES6 Class properties to be concealed by Higher Order Functions?

UPDATE: Added new screenshots to provide clarity at the end.

My current challenge involves utilizing high order functions to combine subclasses/mixins. I've noticed that I can only access properties from the first class I extend, and only properties from subsequent classes after calling the class. Here's a simplified example to illustrate my point:

Below are the functions responsible for applying subclasses to the parent class:

export const middleNameClass = middlename => BaseClass => {
  return class extends BaseClass {
    constructor(args) {
      super(args);
      this.middlename = middlename;
    }
  };
};

export const lastNameClass = lastname => BaseClass => {
  return class extends BaseClass {
    constructor(args) {
      super(args);
      this.lastname = lastname;
    }
  };
};

Next is firstNameClass, directly extended by the parent class, Person:

class firstNameClass {
  constructor(args) {
    this.firstname = args;
  }
}

This is Person, extending firstNameClass:

class Person extends firstNameClass {
  constructor(args) {
    super(args);
    this.getNames = this.getNames.bind(this);

    // To log class properties to console
    this.getNames();
  }

  getNames() {
    console.log("this inside getNames(): ", this);
    console.log("firstnames inside getNames(): ", this.firstname);
    console.log("middlenames inside getNames(): ", this.middlename);
    console.log("lastnames inside getNames(): ", this.lastname);
  }
}

Finally, here's where I apply higher order functions and create the class:

const enhancedClass = compose(
  middleNameClass("Allan"),
  lastNameClass("Poe")
)(Person);

const namedPerson = new enhancedClass("Edgar");

Upon checking the console.log, I observe the following outcomes:

this.firstnames inside getNames(): Edgar
this.middlenames inside getNames(): undefined
this.lastnames inside getNames(): undefined

If someone could shed light on what I might be missing or doing incorrectly, it would be greatly appreciated.

UPDATE: The code snippet of my Person class can be found here: https://i.sstatic.net/yGuRA.png

Additionally, here is the output displayed in the console after creating the class: https://i.sstatic.net/BgbxD.png

Answer №1

When you create a new instance of enhancedClass('Edgar'), the following sequence occurs:

  • The constructor of lastNameClass calls super
  • The constructor of middleNameClass calls super
  • The constructor of Person calls super
  • firstNameClass assigns 'Edgar' to this.firstName
  • You return to Person, which invokes getNames
  • You return to middleNameClass, which assigns 'Allan' to this.middleName
  • You return to lastNameClass, which assigns 'Poe' to this.lastName

If you call getNames afterwards, it should function correctly. The same result would have been achieved by using extend every time.

Answer №2

While this may not directly answer your question, it could offer a solution to the issue at hand

In JavaScript, multiple inheritance is not supported. However, functional programming in no way relies on JavaScript's class system, object prototypes, or other object-oriented concepts. Functional programming revolves around functions!

To create inheritable modules, we start by defining some functions

// module 1
const hasFirstName = (firstName = "") => o =>
{
  field (o, 'firstName', firstName)
}

// module 2
const hasMiddleName = (middleName = "") => o =>
{
  field (o, 'middleName', middleName)
}
  
// module 3
const hasLastName = (lastName = "") => o =>
{
  field (o, 'lastName', lastName)
}

We haven't defined field yet, but let's explore a more complex module next

// module 4
const nameable = (first, middle, last) => o =>
{
  inherit (o, hasFirstName (first))
  inherit (o, hasMiddleName (middle))
  inherit (o, hasLastName (last))
  method (o, 'getFullName', (self) => `${self.firstName} ${self.middleName} ${self.lastName}`)
  method (o, 'sayHelloTo', (self, other) => `Hello ${other.getFullName ()}, my name is ${self.getFullName ()}`)
}

This showcases how modules can be composed of one another. Before diving into inherit and method, let's see how our module would be used

const Person = (first, middle, last) =>
  Obj (self => {
    inherit (self, nameable (first, middle, last))
  })

It might seem like I'm crafting new code with each example, but this "wishful thinking" technique is potent

"Wishful Thinking" is a powerful programming strategy:

Prior to implementing a component, write some code that actually utilizes it. This approach helps identify the necessary functions and parameters for an efficient interface. It also serves as good test code for the component.

The concept emphasizes that an interface should simplify the code using the component, not the code implementing it.

By employing this strategy, we constructed an imaginary object system based on desired functionality – not limited by JavaScript's native capabilities

Expect working with our Person to be straightforward

const p1 =
  Person ('Augusta', 'Ada', 'King-Noel', 166)

const p2 =
  Person ('Gerald', 'Jay', 'Sussman', 71)

console.log (p1.sayHelloTo (p2))
// Hello Gerald Jay Sussman, my name is Augusta Ada King-Noel

The beauty here lies in the absence of class or this. Even without JavaScript's built-in object system, you can forge your own

const Obj = (f, instance = {}) =>
  (f (instance), instance)
  
const inherit = (o, f) =>
  Object.assign (o, f (o))

const field = (o, name, value) =>
  Object.assign (o, { [name]: value })

const method = (o, name, f) =>
  Object.assign (o, { [name]: (...xs) => f (o, ...xs) })

Full program demonstration

// DIY class system
const Obj = (f, instance = {}) =>
  (f (instance), instance)
  
const inherit = (o, f) =>
  Object.assign (o, f (o))

const field = (o, name, value) =>
  Object.assign (o, { [name]: value })

const method = (o, name, f) =>
  Object.assign (o, { [name]: (...xs) => f (o, ...xs) })

// module 1
const hasFirstName = (firstName = "") => o =>
{
  field (o, 'firstName', firstName)
}

// module 2
const hasMiddleName = (middleName = "") => o =>
{
  field (o, 'middleName', middleName)
}
  
// module 3
const hasLastName = (lastName = "") => o =>
{
  field (o, 'lastName', lastName)
}

// module 4
const nameable = (first, middle, last) => o =>
{
  inherit (o, hasFirstName (first))
  inherit (o, hasMiddleName (middle))
  inherit (o, hasLastName (last))
  method (o, 'getFullName', (self) => `${self.firstName} ${self.middleName} ${self.lastName}`)
  method (o, 'sayHelloTo', (self, other) => `Hello ${other.getFullName ()}, my name is ${self.getFullName ()}`)
}

// Person class
const Person = (first, middle, last) =>
  Obj (self => {
    inherit (self, nameable (first, middle, last))
  })

// demo
const p1 =
  Person ('Augusta', 'Ada', 'King-Noel')

const p2 =
  Person ('Gerald', 'Jay', 'Sussman')

console.log (p1.sayHelloTo (p2))
// Hello Gerald Jay Sussman, my name is Augusta Ada King-Noel

Our Person class can obviously define its own fields and methods as well

const dateDiff = (d1, d2) =>
  Math.abs (d1 - d2) / 1000 / 60 / 60 / 24 / 365 >> 0

const Person = (first, middle, last, birthdate = new Date) =>
  Obj (self => {
    inherit (self, nameable (first, middle, last))
    field (self, 'birthdate', birthdate)
    method (self, 'calculateAge', (self) => dateDiff (new Date, self.birthdate))
    method (self, 'sayAge', (self) => `I am ${self.calculateAge()} years old`)
  })

const p2 =
  Person ('Gerald', 'Jay', 'Sussman', new Date ('February 8, 1947'))

console.log (p2.sayAge ())
// I am 71 years old

Get creative and invent any other features you want

  • Consider adding an overrideMethod to define a new method with the same name while retaining access to both
  • Explore possibilities like privateMethod or classMethod helpers
  • Possibly enhance field to emit events when values change
  • Contemplate restricting value setting with mutableField for changeable fields

Design it according to your preferences and bring your ideas to life. Your only limitations are those you impose upon yourself

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Organizing data in a bar chart with D3.js through the d3.nest() function

I am new to d3.js and my JavaScript skills are at a basic level. Thank you for your assistance, it is greatly appreciated. Total Clicks per Campaign I have a CSV file with columns: "Campaign" and "Clicked". The "Clicked" column contains values: Clicked ...

"Injecting the value of a jQuery variable into a PHP variable

<script type="text/javascript"> $(document).ready(function(){ $("#t_select").change(function(){ var table_name = $("#t_select").val(); $.ajax({ type: 'POST', ...

What is the process for triggering a PHP function when a form element is clicked in a webpage?

Currently, I am trying to implement a jQuery colorbox on my webpage which appears over a <select> drop-down list. My goal is to trigger an AJAX call every time a new option is selected from the drop-down. Even though I have written the following cod ...

Can Node.js be utilized to generate an XLS excel file while specifying the cell type?

I've noticed that many libraries have the capability to export to XLSX (Excel > 2007) or CSV formats, but not in XLS (which I assume is due to its outdated file format). I came across something where if you use fs.createOutputStream("filename. ...

Retrieving data from a directive in an HTML table

Utilizing AngularJS, I am seeking a method to retrieve the value from an input located within a specific row in a table. Presented below is an input element. Upon clicking the "add" button, my objective is to extract the value corresponding to that partic ...

What causes the index link to break when react-router's setRouteLeaveHook is used?

Issue: Whenever I include router.setRouteLeaveHook() or router.listenBefore() in my component, it causes the logo homepage Link to path="/" to break Scenario: I am attempting to implement a confirmation prompt before leaving a section. Below is the code f ...

Looking to grasp the concept of calling inline functions within a React functional component

As a newcomer to React, I recently created a new view within my company. Following the example of many guides, I have utilized inline functions and function components exclusively. One common practice I have adopted is writing onClick events in this manne ...

Is it possible to use JavaScript to click on a particular point or element within a canvas?

Is there a way to trigger a click at a specific point on a canvas without direct access to the code that generates it? I've attempted using coordinates, but haven't had any success. Any alternative suggestions would be appreciated. UPDATE: To pr ...

Using dynamic jquery to target specific elements. How can we apply jquery to selected elements only?

Hello everyone! I have been working on a simple hover color change effect using jQuery, but I noticed that I am repeating the code for different buttons and service icons. Is there a way to achieve the same result so that when a button is hovered, the co ...

Adjust the background color using jQuery to its original hue

While working on a webpage, I am implementing a menu that changes its background color upon being clicked using jQuery. Currently, my focus is on refining the functionality of the menu itself. However, I've encountered an issue - once I click on a men ...

Hiding and showing div elements using CSS, JavaScript, and PHP

Here is the current code snippet: <? while ($row1 = mysql_fetch_object($result1)) { echo '<a href="#" onclick="showhide("'.$row1->id.'");">Name</a>'; while ($row2 = mysql_fetch_object($result2)) { ...

Is there a way to identify the specific button that was clicked within an Angular Material dialog?

import {Component, Inject} from '@angular/core'; import {MdDialog, MdDialogRef, MD_DIALOG_DATA} from '@angular/material'; /** * @title Dialog Overview Example with Angular Material */ @Component({ selector: 'dialog-overview-ex ...

JQuery Form Validation - Detecting Input Changes

Currently, I have a form set up with jQuery validation that works well, but I want to enhance its functionality. The form uses a plugin for validation, but it only checks for errors upon submission. I'm interested in finding a way to validate the fiel ...

The fadein feature in Deps.Autorun is not functioning as expected in Meteor version 0.5.9

Here is the code I am currently working with: Template.jobFlash.helpers({ latest_job: function(){ if(Session.get("latestJob")!=""){ return JobsCollection.findOne({}, {sort: {'added_date': -1}}); } } }); Deps. ...

Socket.io continuously refreshing and updating multiple instances

Incorporating socket.io into a small React application, I configured all the listeners within the "componentWillMount" method. See the code snippet below for reference: componentWillMount() { const socket = io(); socket.on('update', f ...

When attempting to call a Firebase Cloud Function URL in an AngularJS $http request, an Access Control Origin Error

I recently created a cloud function that involves linking with Plaid. I'm currently working on calling this function using AngularJS's $http method. While the cloud function code is being executed, I encountered an error in my console instead of ...

Encountering a Nuxt error where properties of null are being attempted to be read, specifically the 'addEventListener' property. As a result, both the default

Currently, I am utilizing nuxt.js along with vuesax as my UI framework. I made particular adjustments to my default.vue file located in the /layouts directory by incorporating a basic navbar template example from vuesax. Subsequently, I employed @nuxtjs/ ...

Retrieve the string data from a .txt document

I am facing an issue with my script that retrieves a value from a .txt file. It works perfectly fine when the value is a number, but when trying to fetch text from another .txt file, I encounter the "NaN" error indicating it's not a number. How can I ...

Loading Data into Array - Angular/Ionic

I am currently developing an App and encountering issues with pushing data into an array. It seems that there is a problem in my code. Would you mind taking a look? Error Message Thrown: ionic.bundle.js:25642 TypeError: Cannot read property 'title&ap ...

Analyzing Compatibility and Ensuring Security

I recently started using Parse and have been exploring the documentation and answered questions. However, I still have a couple of inquiries on my mind. Firstly, I discovered that the Javascript SDK does not function on IE9 and IE8 without an SSL certific ...