多个构造函数的JavaScript模式

cod*_*lic 97 javascript oop design-patterns

我的实例需要不同的构造函数.那是什么常见模式?

bob*_*nce 109

JavaScript没有函数重载,包括方法或构造函数.

如果您希望函数的行为有所不同,具体取决于传递给它的参数的数量和类型,您必须手动嗅探它们.JavaScript会愉快地调用一个函数,其函数的数量多于或少于声明的参数数量.

function foo(a, b) {
    if (b===undefined) // parameter was omitted in call
        b= 'some default value';

    if (typeof(a)==='string')
        this._constructInSomeWay(a, b);
    else if (a instanceof MyType)
        this._constructInSomeOtherWay(a, b);
}
Run Code Online (Sandbox Code Playgroud)

您还可以arguments像数组一样访问以获取传入的任何其他参数.

如果您需要更复杂的参数,最好将其中的部分或全部放入对象查找中:

function bar(argmap) {
    if ('optionalparam' in argmap)
        this._constructInSomeWay(argmap.param, argmap.optionalparam);
    ...
}

bar({param: 1, optionalparam: 2})
Run Code Online (Sandbox Code Playgroud)

Python演示了如何使用default和named参数以比函数重载更实际和更优雅的方式覆盖大多数用例.JavaScript,不是那么多.

  • 谢谢,这真的很好。我想说第二种选择不仅对您有复杂的参数有用,而且对难以区分的参数也很有用,例如,支持`MyObj({foo:“ foo”})`加上`MyObj({bar: “ bar”})`。MyObj有两个构造函数-但都带有一个参数,它是一个字符串:-) (2认同)

mah*_*azi 51

您可以将类与返回该类实例的静态方法一起使用

    class MyClass {
        constructor(a,b,c,d){
            this.a = a
            this.b = b
            this.c = c
            this.d = d
        }
        static BAndCInstance(b,c){
            return new MyClass(null,b,c)
        }
        static BAndDInstance(b,d){
            return new MyClass(null,b, null,d)
        }
    }

    //new Instance just with a and other is nul this can
    //use for other params that are first in constructor
    const myclass=new MyClass(a)

    //an Instance that has b and c params
    const instanceWithBAndC = MyClass.BAndCInstance(b,c)

    //another example for b and d
    const instanceWithBAndD = MyClass.BAndDInstance(b,d)
Run Code Online (Sandbox Code Playgroud)

使用此模式,您可以创建多构造函数

  • 这是最好的答案。其他人则诉诸于解析数组并做一堆不必要的工作。 (7认同)

cod*_*lic 28

你怎么找到这个?

function Foobar(foobar) {
    this.foobar = foobar;
}

Foobar.prototype = {
    foobar: null
};

Foobar.fromComponents = function(foo, bar) {
    var foobar = foo + bar;
    return new this(foobar);
};
Run Code Online (Sandbox Code Playgroud)

  • 我不明白.您可以在实际使用它的地方添加代码吗?你每次都要打电话给组件吗?因为那不是真正的构造函数,而是辅助函数.@ bobince的答案似乎更准确. (8认同)
  • 返回新的(foobar); 不起作用.我换回新的Foobar(foobar); 一切都是正确的. (2认同)
  • 如果这行得通,那就是一个复杂的模式。 (2认同)

Jac*_*Kay 12

不像在bobince的答案那样用手工做,所以我只是完全扯掉了jQuery的插件选项模式.

这是构造函数:

//default constructor for Preset 'class'
function Preset(params) {
    var properties = $.extend({
        //these are the defaults
        id: null,
        name: null,
        inItems: [],
        outItems: [],
    }, params);

    console.log('Preset instantiated');
    this.id = properties.id;
    this.name = properties.name;
    this.inItems = properties.inItems;
    this.outItems = properties.outItems;
}
Run Code Online (Sandbox Code Playgroud)

以下是不同的实例化方法:

presetNoParams = new Preset(); 
presetEmptyParams = new Preset({});
presetSomeParams = new Preset({id: 666, inItems:['item_1', 'item_2']});
presetAllParams = new Preset({id: 666, name: 'SOpreset', inItems: ['item_1', 'item_2'], outItems: ['item_3', 'item_4']});
Run Code Online (Sandbox Code Playgroud)

而这就是:

presetNoParams
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]}

presetEmptyParams
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]}

presetSomeParams
Preset {id: 666, name: null, inItems: Array[2], outItems: Array[0]}

presetAllParams
Preset {id: 666, name: "SOpreset", inItems: Array[2], outItems: Array[2]}
Run Code Online (Sandbox Code Playgroud)


lau*_*ine 9

进一步了解eruciform的答案,您可以将您的new呼叫链接到您的init方法中.

function Foo () {
    this.bar = 'baz';
}

Foo.prototype.init_1 = function (bar) {
    this.bar = bar;
    return this;
};

Foo.prototype.init_2 = function (baz) {
    this.bar = 'something to do with '+baz;
    return this;
};

var a = new Foo().init_1('constructor 1');
var b = new Foo().init_2('constructor 2');
Run Code Online (Sandbox Code Playgroud)


Ars*_*aev 9

export default class Order {

    static fromCart(cart) {
        var newOrder = new Order();
        newOrder.items = cart.items;
        newOrder.sum = cart.sum;

        return newOrder;
    }

    static fromOrder(id, order) {
        var newOrder = new Order();
        newOrder.id = id;
        newOrder.items = order.items;
        newOrder.sum = order.sum;

        return newOrder;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用:

  var newOrder = Order.fromCart(cart)
  var newOrder = Order.fromOrder(id, oldOrder)
Run Code Online (Sandbox Code Playgroud)


Dal*_*oft 8

回答是因为这个问题首先在谷歌中返回,但答案现在已经过时了。

您可以在 ES6 中使用Destructuring 对象作为构造函数参数

这是模式:

你不能有多个构造函数,但你可以使用解构和默认值来做你想做的事。

export class myClass {

  constructor({ myArray = [1, 2, 3], myString = 'Hello World' }) {

    // ..
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您想支持“无参数”构造函数,则可以执行此操作。

export class myClass {

      constructor({myArray = [1, 2, 3], myString = 'Hello World'} = {}) {

        // ..
      }
}
Run Code Online (Sandbox Code Playgroud)