문제

A function I wrote takes an object as only argument, and naturally I need this object to follow a particular object specification (what properties it has, of what type, etc.).

Instead of passing it as an object literal and do all the checking within the function, I had the idea to write a "constructor" function to which you pass that literal object, and that does all the job of enforcing the object specification, plus providing default values if necessary.

This function won't be called with new because it has no need for prototypal inheritance. The return object may include a special property (_isAPoint in the example) to "prove" that the object was properly constructed (a replacement for instanceof).

I don't remember having seen this kind of approach before. At first sight, it seems a clean way to create valid argument objects, while avoiding the whole mechanism of prototypal inheritance.

What do you think? Is this an identified pattern? Could you point me to possible drawbacks and improvements?

Simplified example:

var Point = function (opts) {
    "use strict";
    var defaults = {
        color: "blue",
        x: 0
    };

    opts = $.extend(defaults, opts); // (using jQuery's extend)

    if (!isNan x) {
        throw new Error("x must be a number");
    }

    return {
        _isAPoint: true,
        color: opts.color,
        x: opts.x
    };
};

Called like this:

someNiceMap.addPoint(Point({ x: 2, color: "red" });
someNiceMap.addPoint(Point({ x: 14 });
도움이 되었습니까?

해결책

What you show is called a Factory Method Pattern.

There is no fundamental flaw in this approach and it is considered an alternative to the constructor pattern.

Pros and cons of both approaches are presented in this blog entry by Eric Elliot:

http://ericleads.com/2013/01/javascript-constructor-functions-vs-factory-functions/

As you can see the only important drawback is the inability to use this to refer to the newly created object.

But is it a drawback? Be warned that Eric is known for being against constructor function in favor of factory methods.

To make your code cleaner, make the factory method explicit:

var point = {

   create : function( opts ) { 
      ...
      return {
        _isAPoint: true,
        color: opts.color,
        x: opts.x
      };
   }
}

The call is now cleaner:

someNiceMap.addPoint( point.create( ... ) );
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top