简体   繁体   English

JavaScript中长构造函数的最佳实践

[英]Best Practices for Long Constructors in JavaScript

I'm creating objects with lots of properties and I'm curious about best practices for instantiating them. 我正在创建具有大量属性的对象,我对实例化它们的最佳实践感到好奇。 It seems like it's pretty bad to have really long constructors (instantiating new objects is not fun). 看起来真的很长的构造函数(实例化新对象并不好玩)似乎很糟糕。

 function Book(title, author, pages, chapters, publisher, datePublished, authorHometown, protagonistFavoriteColor) { this.title = title; this.authorpages = authorpages; this.pages = pages; this.chapters = chapters; this.publisher = publisher; this.datePublished = datePublished; this.authorHometown = authorHometown; this.protagonistFavoriteColor = protagonistFavoriteColor; } // not reliable to remember how to order params var rc = new Book("Robinson Crusoe", "Daniel Defoe", 342, 16, ...); 

I'm wondering if perhaps I should just set maybe three important properties in the constructor (egtitle, author, and pages) and write individual setters for the rest. 我想知道是否应该在构造函数中设置三个重要的属性(egtitle,author和pages),并为其余部分编写单独的setter。 Or for consistency should I only use setters? 或者为了保持一致,我应该只使用setter吗? If setting this way is the best path to follow, is there a good way in JS to mandate that those methods be called (kind of like interfaces in Java)? 如果设置这种方式是最好的方法,JS是否有一种很好的方法来强制要求调用这些方法(类似于Java中的接口)?

 function Book (title, author, pages){ this.title = title; this.author = author; this.pages = pages; this.chapters = null; this.publisher = null; this.datePublished = null; this.authorHometown = null; this.protagonistFavoriteColor = null; } var rc = new Book("Robinson Crusoe", "Daniel Defoe", 342); rc.setChapters(16); rc.setPublisher("John Smith Co."); rc.setDatePublished("04-25-1719"); rc.setAuthorHometown("London"); rc.setProtagonistFavoriteColor("lilac"); // we'd also want to mandate that these setters be called so nothing is left null 

Lastly, would passing in an object to my constructor and destructuring it total defeat the pt of a constructor? 最后,将一个对象传递给我的构造函数并将其解构完全失败了构造函数的pt?

Seems like it might be best to use an arguments object and a mixin. 似乎最好使用arguments对象和mixin。 This is kind of a double edged sword in that it makes the code that instantiates the object easier to read, but the constructor itself a little less obvious. 这是一种双刃剑,因为它使实例化对象的代码更容易阅读,但构造函数本身不太明显。 eg 例如

function Book(args) {
     Object.assign(this, args);
}

var rc = new Book({
    name:   "Robinson Crusoe",
    author: "Daniel Defoe",
    pages:  342
});

If you want default values, then you can implement that with another mixin eg 如果你想要默认值,那么你可以用另一个mixin实现它,例如

function Book(args) {
    args = Object.assign(args, {
       protagonistFavoriteColor: "Red"
    });

    Object.assign(this, args);
 }

Then an invocation such as : 然后调用如:

var rc = new Book({
    name:   "Robinson Crusoe",
    author: "Daniel Defoe",
    pages:  342
});

Would give : 会给:

rc.author; // "Daniel Defoe"
rc.protagonistFavoriteColor // "Red"

If you want to make sure certain values are provided, you would need to test at the end of the constructor that those are present and throw an Error. 如果要确保提供某些值,则需要在构造函数的末尾测试那些值是否存在并抛出错误。

In es6 you can use destructuring and Object.assign to simplify the copy constructor pattern (a constructor taking a parameter-laden object as its single argument): 在es6中,您可以使用destructuringObject.assign来简化复制构造函数模式(将带参数的对象作为其单个参数的构造函数):

 function Book({title, author, pages, chapters, publisher, datePublished, authorHometown, protagonistFavoriteColor}) { Object.assign(this, {title, author, pages, chapters, publisher, datePublished, authorHometown, protagonistFavoriteColor}); } var rc = new Book({title: "Robinson Crusoe", author: "Daniel Defoe", pages: 342, chapters: 16}); var copy = new Book(rc); console.log(JSON.stringify(rc)); console.log(JSON.stringify(copy)); console.log(copy == rc); // false 

It's called that, because you can now conveniently create an object from another instance. 它被称为,因为您现在可以方便地从另一个实例创建一个对象。

We enumerate each property in Object.assign , to assign only valid parameters. 我们枚举Object.assign每个属性,仅分配有效参数。

Does this defeat the purpose of having a constructor in the first place? 这是否会破坏首先拥有构造函数的目的? If this is all you class does, then yes. 如果这是你所做的全部,那么是的。 Yes it does. 是的,它确实。 But hopefully your class has some methods and purpose to it other than this. 但希望你的班级除此之外还有一些方法和目的。

Best practice would be to pass an object defining properties into constructor: 最佳做法是将定义属性的对象传递给构造函数:

function Book(props) {
  // create variables out of object (if you need to)
  const {
    title,
    author,
    pages,
    chapters,
    publisher,
    datePublished,
    authorHometown,
    protagonistFavoriteColor
  } = props;

  // assign properties to instance object
  Object.assign(this, props);
}

const rc = new Book({
  title: "Robinson Crusoe",
  author: "Daniel Defoe",
  pages: 342,
  chapters: 16,
  // rest of properties
});

console.log(rc);

JSFiddle Demo: https://jsfiddle.net/Lr6umykn/3/ JSFiddle演示: https ://jsfiddle.net/Lr6umykn/3/

I know this is an old request but I wonder why no one mentioned complex objects. 我知道这是一个旧请求,但我想知道为什么没有人提到复杂的对象。 In my opinion, this is the easiest way to organize and store your data. 在我看来,这是组织和存储数据的最简单方法。

  1. create your constructor with ES6 destructuring : 使用ES6解构创建构造函数:
function Book({reference, publication, author}) {
    this.reference = reference;
    this.publication = publication;
    this.author = author;
}
  1. Instantiation : 实例化:
var rc = new Book({
    reference: {
        title: 'Robinson Crusoe',
        pages: 342,
        chapters: 16,
        protagonistFavoriteColor: 'lilac'
    },
    publication: {
        publisher: 'John Smith co.',
        date: '04-25-1719'
    },
    author: {
        name: 'Daniel Defoe',
        homeTown: 'London'
    }
});
  1. Usage : 用法:
console.log(rc.reference.title); // 'Robinson Crusoe'
console.log(rc.publication.date); // '04-25-1719'
console.log(rc.author.name); // 'Daniel Defoe'

This method also give you the possibility to access an entire category. 此方法还使您可以访问整个类别。

console.log(rc.author); // {name: "Daniel Defoe", homeTown: "London"}

console.log(rc.reference); // {title: "Robinson Crusoe", pages: 342, chapters: 16, protagonistFavoriteColor: "lilac"}

Once you're familiar with this organization, it is simple and fun to create objects. 熟悉此组织后,创建对象既简单又有趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM