传递参数到类构造函数

5
我已经编写了下面的模块,但是导入它时出现了问题。文件(为简化起见而缩写): templates.js
'use strict';

export default class Templates {
    constructor (args) {
        this.files = [{
            name: `${args.name}.js`,
            path: 'src/',
            content: ''
        }];
        /* code omitted */
    }
};

我将翻译成如下内容:

我尝试这样使用它:

index.js

import Templates from './templates'

const opts = {name: 'app'};
/* code ommited */
console.log('Templates >>', typeof Templates);
console.log('Templates >>', new Templates());

let tmpls = new Templates(opts);
console.log(tmpls.files[0].name);

但我在控制台中看到了以下错误跟踪。
npm ERR! Linux 3.16.0-38-generic
npm ERR! argv "/home/wesleycoder/.nvm/versions/node/v5.1.0/bin/node" "/home/wesleycoder/.nvm/versions/node/v5.1.0/bin/npm" "init"
npm ERR! node v5.1.0
npm ERR! npm  v3.3.12

npm ERR! Cannot read property 'name' of undefined

是的,这是一个~/.npm-init脚本,供需要的人使用。

编辑:感谢@low_ghost提供有用的回答。

我发现我的问题不在于导出和导入类。 实际上,它是关于传递参数给这个类,而不是不传递参数。所以我改变了标题以简洁明了。

我的代码中意图将console.log(new Templates())没有任何参数。 我试图解决的错误是关于实例化对象并获取文件数组,但我直接从commander.js库传递参数,传递的参数对于此任务来说是“过度”,因此我通过从commander.js获取输入并将每个输入分配到空对象的属性中,然后沿着构造函数传递这个对象,这使我可以从readline-sync获取输入,并从未传递的选项读取输入,使脚本更加完美,之后一切都运行正常。

如果commander.js有任何选项可以提供传递的选项而不带有额外的库属性,那就太好了。

编辑2:毕竟commander.js没有用,因为我无法将参数传递给脚本本身的npm init命令。


1
只是为了澄清:这个问题与Babel或ES6无关。 - Felix Kling
2个回答

10

由于构造函数调用时参数缺失,导致名称未定义。最佳解决方案取决于意图,可以检查名称的存在和类型:

 'use strict';

 export default class Templates {
   constructor (args) {
     this.files = (args.name && typeof arg.name === "string")
       ? [{
           name: `${args.name}.js`,
           path: 'src/',
           content: ''
         }]
       : [];
    /* other code */
   }
};

如果您对三元运算符感到满意,那么如果arg.name不存在或不是字符串,则会返回一个空数组作为this.files。
编辑:
或者,正如madox2建议的那样,提供一个默认值。虽然我会为名称提供默认值,而不是为整个args对象提供默认值。就像这样:
 constructor({ name = 'defaultName', ...otherArgs } = {})

那么,如果您调用了以下内容:
 new Templates({ dir: 'repo' })

即使你使用默认名称,如果你按字面理解省略号,你也可以从otherArgs.dir中获取dir。= {} 部分允许调用。

 new Templates()

仍然获得默认名称。


{ name = 'defaultName', ...otherArgs } 不是有效的 JavaScript 代码。 - vkurchatkin
@vkurchatkin: 当然可以。查找解构。 - Felix Kling
我指的是 ...otherArgs 部分。 - vkurchatkin
@vkurchatkin:我明白了。那是一个ES7的提案,可以在Babel中启用。 - Felix Kling
ES7 意味着它将成为 2016 年规范版本的一部分,但目前还不确定。无论如何,最好避免提议的语法扩展,除非问题直接相关。 - vkurchatkin
显示剩余2条评论

1

Templates类的构造函数需要一个对象作为参数。如果您不传递它,args参数将是undefined,并且当您调用args.name时会失败。请尝试以下操作:

console.log('Templates >>', new Templates({}));

或者:
console.log('Templates >>', new Templates({name: 'myName'}));

您还可以在构造函数中设置默认参数值,然后无需参数调用它:

constructor (args = {name: 'defaultName'}) {
    //...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接