Skip to main content

Prototype Pattern_JavaScript Design Patterns 6

Free2015-07-22#JS#Design_Pattern#JavaScript原型模式#Prototype_Pattern

Prototype pattern, also known as Douglas's beget method, creates new objects based on existing objects as prototypes, similar to inheritance but more like copying. This article details the prototype pattern implemented in JavaScript

1. Prototype Pattern

Using existing objects as prototypes, get new objects through clone (to simplify the creation process of new objects)

(From [Ayqy: Design Patterns Summary ("Head First Design Patterns" Learning Summary)](/articles/设计模式总结(《head-first 设计模式》学习总结)/))

Very similar to inheritance, enhancing the prototype pattern further becomes inheritance. Prototype pattern only cares about attribute copying, while inheritance besides implementing attribute copying also needs to ensure parent/child type hierarchy relationships

2. Specific Implementation

1. Basic Principle

// Beget function
function beget(obj) {
    var F = function() {};
    F.prototype = obj;
    return new F();
}

// test
var obj = {
    attr: 1,

    fun: function() {
        console.log(this.attr);
    }
}
var cp_obj = beget(obj);
cp_obj.fun();   // 1

Core is the beget function, puts the passed object into empty constructor's prototype, creates object and returns, that's all

One obvious disadvantage: attributes from prototype object (in this case obj) may be accidentally overwritten

P.S. Prototype object obj can be an object created in any way, in this case is object literal, of course can also be new'ed, can be beget'ed, etc.

2. Simple Enhancement

ES5 supports Object.create function to get shallow copied objects, can directly replace beget with:

Object.create(obj);

Result is exactly the same, because Object.create internal implementation is inspired by Douglas's prototype pattern, additionally Object.create can have a second parameter, used to define attributes:

Object.create(obj, {
    attr: {
        value: 2,
        writable: false,        // default value
        configurable: false,    // default value
        enumerable: true
    }
});

Actually combines Object.create and Object.defineProperty together, for example:

// test
var obj = {
    attr: 1,

    fun: function() {
        console.log(this.attr);
    }
}
var cp_obj = Object.create(obj, {
    attr2: {
        value: 2,
        writable: false,        // default value
        configurable: false,    // default value
        enumerable: true
    }
});
cp_obj.fun();   // 1
console.log(cp_obj.attr2);  // 2
cp_obj.attr2 = 3;
console.log(cp_obj.attr2);  // 2, not writable

Of course, Object.defineProperty is also only supported from ES5, so using together counts as an enhancement (access control)

3. Benefits of Prototype Pattern

There's a nice sentence in the book:

One of the benefits of using the Prototype pattern is that we gain the prototype advantages that JavaScript itself possesses, rather than trying to imitate characteristics of other languages.

Prototype pattern implemented in Java looks very strange, because for the prototype pattern itself, Java's Object.clone can already satisfy the needs, any other form of implementation seems redundant, while JavaScript initially didn't provide clone native implementation (ES5's Object.create makes up for this defect), so needs prototype pattern, after ES5 goes into production no longer needs to manually implement any prototype pattern

For more introduction about prototype pattern please check 23 Design Patterns (5): Prototype Pattern

Reference Materials

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment