An abbreviated way to initialize a class in ECMAScript 6

Tired of going through the monotonous process every time I create a new class:

class Something {
  constructor(param1, param2, param3, ...) {
    this.param1 = param1;
    this.param2 = param2;
    this.param3 = param3;
    ...
  }
}

Looking for a more streamlined and concise solution. Utilizing Babel with the flexibility of ES7 experimental features. Could decorators offer assistance?

Answer №1

If you want a concise way to assign properties in JavaScript, consider using Object.assign:

class Thing {
  constructor(prop1, prop2, prop3) {
    Object.assign(this, {prop1, prop2, prop3});
  }
}

This ES2015 (also known as ES6) feature allows you to transfer the own enumerable properties from one or more source objects to a target object.

While it may require repetition of argument names, this method is significantly shorter. Establishing it as your standard approach handles instances where certain arguments should be kept on the instance while others should not be, such as:

class Thing {
  constructor(prop1, prop2, prop3) {
    Object.assign(this, {prop1, prop3});
    // Deal with prop2 separately if needed 
  }
}

For example, see the code snippet below (live copy on Babel's REPL):

class Thing {
  constructor(prop1, prop2, prop3) {
    Object.assign(this, {prop1, prop2, prop3});
  }
}
let t = new Thing('x', 'y', 'z');
console.log(t.prop1);
console.log(t.prop2);
console.log(t.prop3);

Output:

x
y
z

Answer №2

Regrettably, the only options available to you are basic methods like Object.assign. If your goal is to eliminate the repetition of entering parameters twice (in both the constructor signature and assignment), there isn't much more you can do.

However, you could implement a workaround like this example below. Although, the complexity and slight obfuscation it introduces may not be worthwhile in the end.

var dependencies = ['param1', 'param2', 'param3'];

class Something {
  constructor(...params) {
    params.forEach((param, index) => this[dependencies[index]] = param);
  }
}

var something = new Something('foo', 'bar', 'baz');
// something.param1 === 'foo'

In this approach, you utilize a single array containing argument names, then reference that same array when setting the properties on your instance of Something. This method could be particularly useful in an Angular application where preserving dependency names during minification is important by utilizing the $inject property.

Something.$inject = dependencies;

PS - Welcome to the redundant labyrinth of traditional languages that I assumed I had escaped when transitioning to JS development :P

Realistically, using a classic object literal might be a simpler solution unless the formal structure of a true class is essential.

Edit: Alternatively, if you prefer the simplicity of an object literal combined with the formality of a class, you could consider accepting an object literal in your constructor.

class Something {
  constructor(params) {
    Object.keys(params).forEach((name) => this[name] = params[name]);
  }
}

var something = new Something({
  param1: 'foo',
  param2: 'bar',
  param3: 'baz'
});

Although, now your class has essentially transformed into a dynamic entity that can be instantiated with any properties, resembling an object literal :P

Typically, the choice to use a class is rooted in the desire to formalize the object and provide a consistent, rigorously testable API.

Answer №3

To streamline the process, we can implement a static method within each class that accepts the arguments object and an array of names. This method will then generate an object that can be easily assigned to a new instance using Object.assign.

For a practical demonstration, refer to the Babel REPL.

class Something {
  static buildArgs (ctx, args, paramNames) {
    let obj = {}
    Array.from(args).forEach(function (arg, i) {
      let name = paramNames[i] || i
      obj[name] = args[i]
    })
    Object.assign(ctx, obj)
  }

  constructor () {
    Something.buildArgs(this, arguments, [
      'param1',
      'param2'
    ]);
    console.log(this)
  }
}

new Something('one', 'two')

The introduction of the buildArgs method might not necessarily decrease the code length, but it does offer several advantages:

  1. You only need to specify the parameter names once.
  2. Your code is protected from minification issues.

If necessary, the code provided above can handle extra arguments (i >= paramNames.length). However, if you prefer to skip assigning these extra arguments to the instance:

class Something {
  static buildArgs (ctx, args, paramNames) {
    let obj = {instance: {}, extra: {}}
    Array.from(args).forEach(function (arg, i) {
      let name = paramNames[i] || i
      if (name) {
          obj.instance[name] = args[i]
      } else {
          obj.extra[i] = args[i]
      }
    })
    Object.assign(ctx, obj)
  }

  constructor () {
    let args = Something.buildArgs(this, arguments, ['param1', 'param2']);
    // Handle `args.extra` separately
  }
}

Alternatively, you can choose to completely ignore the extra arguments:

  static buildArgs (args, paramNames) {
    let obj = {}
    Array.from(args).forEach(function (arg, i) {
      let name = paramNames[i]
      if (name) obj[name] = args[i]
    })
    return obj
  }

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

What is the reason that the <script> tag cannot be directly inserted into the .html() method?

As I continue to learn front-end development, I've created my own version of JS Bin. When the 'run' button is clicked, a statement is executed to showcase the HTML, CSS, and JavaScript in an iframe (the output window): ("iframe").contents() ...

Identifying when the mouse cursor changes on a website

Is there a way to detect when the mouse cursor changes as it hovers over different page elements? An event similar to this would be ideal: window.onmousecursorchange = function(e) { // e would provide information about the cursor // for example, ...

I seem to be having trouble locating the correct file location

Apologies for the simplicity of my question. I've been struggling to include the find.js file in my articles.js file. Despite trying multiple variations, I can't seem to get the pathname right and haven't found a solution online. Can someon ...

Ensure that the jQuery Accordion always displays a table within every div

I have implemented an accordion-style menu that toggles the next div area when clicking its parent h3 element. $(document).ready(function() { $('div.accordian-content').find('div').hide(); $('div.accordian-content').f ...

Converting a string to an array in JavaScript/TypeScript: Tips and Tricks

Is there a way to convert a string, which is formatted like an ordered list, into an array using JavaScript or TypeScript? This is the format in which data is being returned from the backend. The string has the following structure: Lorem Ipsum. 2. Lorem ...

Implement a function within a class

I have a core application that I deploy to various clients and customize based on their specific requirements. Let's say there is a foundational component comprising: component-core.html component-core.ts Now, a client requests customization, promp ...

Retrieving the value of an input tag within dynamically created table rows using JSP

I have encountered an issue where I am only able to fetch the value of the input tag with the id b_quantity field from the first row, even though each row in the table contains a different record. My goal is to target the value of b_quantity in the same ro ...

Extracting a substring using JavaScript within a PHP environment

Can anyone help me with this issue? I need to extract the ID from a link: www.imdb.com/title/tt5807628/ - > tt5807628 This is my javascript code: var str = "www.imdb.com/title/tt5807628/"; var n = str.search("e/tt"); var res = str.substring ...

Basic click event triggered every second click in JavaScript and HTML

onclick="HandleAction(\'playnow\');HandleAction(\'stop\');" This element performs two functions simultaneously. However, it only executes the actions \playnow\ and then \stop\ immediately after. ...

Loading animation reminiscent of a whirlpool, similar to the movement

In my quest for the perfect animation, I have scoured far and wide. Unfortunately, the one I found at http://jsfiddle.net/pedox/yed68/embedded/result/ is created using css, which many browsers do not yet support fully. I also explored , but found it to be ...

What is the best way to set a limit depending on whether a user is currently logged in or not?

I'm facing a challenge while using express and express-rate-limit to restrict download limits for anonymous users. The interesting part is that I want to deactivate the limit if the user object sent with the request is true. How can I achieve this? Be ...

Ways to conceal ng repeat using ng if

My autocomplete feature is set up using ng-repeat to display suggestions and ng-click to change the textbox value. However, I am facing an issue where the suggestion does not disappear when the textbox value is already the same as the suggestion. How can I ...

On the completion of jQuery Ajax when the results have been exhausted

Currently in the process of developing a simple quiz for a client that pulls data from their database using an Ajax call to load questions sequentially. While this setup is working smoothly, I am facing a challenge regarding how to efficiently determine ...

Utilizing ng-if in AngularJS for displaying JSON data

After generating Json Data from a PHP API, I attempted to formulate a MYSQL Query and PHP Script to achieve my desired outcome. However, the process has become overly complex. $data1 = [ { "IDa": "6", "IDusr": "1", ...

Encountering issues with scope: Unable to retrieve value and receiving an error message stating 'Cannot assign value to undefined property'

var mainApp = angular.module("Main", []); mainApp.controller("CtrlMain", [ function ($scope) { $scope.amount = 545 }]);` var app = angular.module("Main", []); app.controller("MainCtrl", [ function ($scope) { $scope.value = 545 ...

Error in AngularJS: Failed to retrieve data using $http.post()

One of my current challenges involves: Transferring text data from HTML form text boxes to the Controller using ng-model and ng-submit directives. Sending this data from the controller to a Service. The Issue at Hand: - I am facing difficulties accessi ...

the value contained in a variable can be accessed using the keyword "THIS"

I recently developed a snippet of code that adds a method to a primitive data type. The objective was to add 10 to a specified number. Initially, I had my doubts about its success and wrote this+10. Surprisingly, the output was 15, which turned out to be ...

Implement a loader in AngularJS to display when transitioning between pages

Is there a way to implement a loader that appears when the page starts changing and only disappears once the entire page is fully rendered to prevent clipping bugs? I have already set up the loader as shown below: $scope.$on('$routeChangeStart' ...

Create a JavaScript variable that is initialized with a value from an AngularJS scope

What is the best way to assign a value from an AngularJS scope variable to a JavaScript variable? For example: xyz.controller({ $scope.country = "Canada"; }); Here's how you can do it in JavaScript: <script> var country = {{scope.countr ...

Display properly formatted JSON data in a Rails view without any escaping needed

After exhausting all options, trying out various helper combinations like raw, html_safe, and to_json along with attempts using ::JSON.encode and CGI.unescape, I still can't seem to properly display well-formed JSON in my view. No matter what I try, i ...