Is there a difference in using a constructor to create an object versus returning an object?

前端 未结 3 358
醉梦人生
醉梦人生 2021-01-20 03:27

Is there any difference in how these functions operate? The first one is more typically of what I think about when thinking of a constructor.

Example 1: using t

3条回答
  •  [愿得一人]
    2021-01-20 03:59

    The first one is a constructor, and can therefore be extended by a prototype, and you can test via instanceof wether the result is an Instance of this type. Downside: if you forget the new-keyword your code will blow up (unless you write a workaround for that into each constuctor)

    And you can't really use apply() with a constructor to pass an array of arguments, when you instantiate a new Object; on the other hand, don't do that, even if you can/could.

    The second one is a factory, not a constructor. Independant wether you use the new-keyword or not. with this implementation it creates Objects that look the same but don't share a type or prototype (although the underlying JS-engine recognizes them as similar and so they share the same hidden Class as long as they have the same properties, added in the same order, ... different topic)
    long story short, neither performance nor memory-footprint suffer from this approach (anymore)

    But you can't check wether they are of the same type, and you don't have a shared prototype that may affect all instances (maybe a pro or a con.)

    My goto-approach If I need inheritance, is kind of a mix of both:
    (if I just need a data-object I usually use a factory and plain objects).

    function Book(conf) {
        var book = Object.create(Book.prototype);
        //a book like this usually has multiple configs/properties
        if(typeof conf === "object"){
            for(var k in conf) book[k] = conf[k];
        }else if(conf){
            //assuming that I get at least the name passed
            book.name = String(conf);
        }
        return book;
    }
    
    //I have a prototype that can be extended
    //with default-values for example; no idea for a good method 
    //to add to the prototype in this example ;)
    Book.prototype.numPages = 0;
    
    //but I can also use it like a plain function; no error if you 
    var myBook1 = Book("Peter Pan");
    var myBook2 = Book({
        name: "American Gods",
        author: "Neil Gaiman"
    });
    

    If I add the following line to the top of the function I can also use that as a method to cast anything into an Instance of Book without cloning already existing instances

    function Book(conf) {
        //with this simple line I can also use this as a function to cast anything into a "Book"
        if(conf instanceof Book) return conf;
    
        var book = Object.create(Book.prototype);
        //...
        return book;
    }
    
    var data = [
        "Peter Pan",
        {name: "American Gods"},
        //...
    ];
    
    var books = data.map(Book);
    

    In my opinion, I have the benefits of both worlds with this approach.

提交回复
热议问题