【问题标题】:ES6 pass an object to constructor and set propertyES6 将对象传递给构造函数并设置属性
【发布时间】:2017-07-03 14:15:28
【问题描述】:

看下面的例子:

class Parent {
    constructor({ parentOnlyArg = 'default value' } = {}) {
        this.parentOnlyArg = parentOnlyArg;
    }
}

class Child extends Parent {
    // this class and also any class inheriting from it
    constructor({ visibleStyle = 'inline' } = {}) {

        // I want to pass argument to super as an object
        super(/** args **/);

        this.visibleStyle = visibleStyle;
    }
}

class Child2 extends Parent {
    // Specifying parentOnlyArg as default will change the behaviour
    constructor({ parentOnlyArg = 'another parent value',
                  someOther = 'value' } = {}) {

        // I want to pass argument to super as an object
        super(/** args **/);

        this.someOther = someOther;
    }
}

是否可以将构造函数参数传递给super?

好像比我想象的要简单

super(...arguments);

然后我可以创建Child 使用

var c1 = new Child(); // c.parentOnlyArg = 'default value'
var c2 = new Child2(); // c.parentOnlyArg = 'another parent value'
var c3 = new Child({ parentOnlyArg: 'changed again' }); // c.parentOnlyArg = 'changed again'

【问题讨论】:

  • 为什么不使用<> sn-p 编辑器发布minimal reproducible example
  • super({parentOnlyArg})?
  • 有什么理由不将解构移动到函数体中?然后,您将获得对要传递的变量的引用。
  • @loganfsmyth 所以你的意思是我应该在super 之前销毁?比如let { parentOnlyArg='value', visibleStyle='inline'} = args 然后super(args)?我不知道是否设置了任何对象成员。我将如何处理? Object.assign 有默认值吗?
  • @bergi 我可以这样做,但是我希望类只使用它感兴趣的参数。在所有情况下,参数都会映射到类成员或忽略它。

标签: javascript class ecmascript-6 es6-class


【解决方案1】:

您可以使用object destructuring with rest properties。它还没有被浏览器实现,但是BabelJs可以转译它。

function assertEmpty(obj) {
  if (Object.keys(obj).length > 0) {
    throw new Error("Unexpected parameters");
  }
}
    
class A {
  constructor({ a = "foo", ...rest } = {}) {
    assertEmpty(rest);
    console.log("new A " + a);
  }
}
    
class B extends A {
  constructor({ b = "bar", ...rest } = {}) {
    super(rest);
    console.log("new B " + b);
  }
}
    
new B({a:2}); // prints 'new A 2', 'new B bar'
new B({a:4, b:5, c:6}); // throws 'Unexpected parameters'

在上面的 sn-p 父类中看不到后代消耗的参数。如果您对此有疑问,可以按照@Bergi 或@loganfsmyth 的建议进行操作。例如:

class A {
  constructor(params = {}) {
    const { a = "foo" } = params;
    console.log("a=" + a);
  }
}

class B extends A {
  constructor(params = {}) {
    const { b = "bar" } = params;
    super(params);
    console.log("b=" + b);
  }
}

new B({a:2}); // prints a=2 b=bar
new B({b:5}); // prints a=foo b=5

【讨论】:

  • 在我刚刚将...arguments 传递给super 的更新中,它似乎也可以工作,我将所有参数传递给父级并保留默认值。您认为该解决方案有什么问题吗?
  • 唯一的问题可能与性能有关,他们说现代浏览器无法优化访问参数对象的函数。不过没关系。
【解决方案2】:

使用arguments 对象是一种速效方法。它是一个数组,包含传递给函数的所有参数。

有关MDN的更多信息。

实际上,感谢arguments[0],您可以访问函数的第一个参数。

class Child extends Parent {
    constructor({ parentOnlyArg = 'value',
                  visibleStyle = 'inline' } = {}) {
        super(arguments[0]);
        [...]
    }
}

【讨论】:

  • 虽然这没有错,但这就是我一周前的做法。缺少其他选择,这将是答案。
猜你喜欢
  • 2013-09-13
  • 2010-11-17
  • 2011-06-12
  • 2014-06-04
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多