-
-
Save cherifGsoul/fe111c0d608794aab92a5805054a0e2d to your computer and use it in GitHub Desktop.
Javascript Code Reuse Patterns
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ---------- | |
| ### Object Creation Patterns | |
| #### Module & Revelation Pattern | |
| Module pattern can define private properties. | |
| It includes several patterns: | |
| - Namespace (unimplemented below) | |
| - Immediate functions | |
| - Private Properties and Methods | |
| - Declaring Dependencies | |
| ```javascript | |
| Space.utilities.method = ( function() { | |
| // declare dependencies | |
| var obj = Space.utilities.object, | |
| // private properties | |
| width = 300, | |
| length = 200; | |
| // private method | |
| getArea = function() { | |
| return width * length; | |
| }; | |
| // revealing public API | |
| return { | |
| getArea : getArea | |
| }; | |
| }()); | |
| var area = Space.method.getArea(); // 60000 | |
| ``` | |
| ---------- | |
| ### Inherited Patterns | |
| #### Default Inherited Pattern #1 | |
| Inherited through the instance of Parent. | |
| ```javascript | |
| function Parent() { | |
| this.tags = ['js', 'css']; | |
| } | |
| Parent.prototype.getTags = function() { | |
| console.log(this.tags); | |
| }; | |
| function Child() {}; | |
| Child.prototype = new Parent; | |
| var kid = new Child(); | |
| kid.getTags(); // ['js', 'css'] | |
| ``` | |
| Usually, we use `inherit()` method to implemente `Child.prototype = new Parent` , as below: | |
| ```javascript | |
| function inherit(child, parent) { | |
| child.prototype = new parent(); | |
| } | |
| inherit(Child, Parent); | |
| ``` | |
| #### Share the Prototype #4 | |
| Comparing to the default inherited pattern, if we change the Parent's prototype, this pattern will effects all the inherited chain. | |
| ```javascript | |
| function inherit(child, parent) { | |
| child.prototype = parent.prototype; | |
| } | |
| ``` | |
| #### Rent a Constructor #2 | |
| In this way, you only inherit those 'this' properties added in Parent's constructor except those members added to Parent's prototype. | |
| ```javascript | |
| function Child(a, b, c, d) { | |
| Parent.apply(this, arguments); | |
| } | |
| ``` | |
| #### Rent and Set Prototype #3 | |
| Different from 'Rent a Constructor', the Child can get the 'this' properties from Parent's constructor and those members added to Parent's prototype. But the defect is the Parent's constructor will be called twice. | |
| ```javascript | |
| function Child(a, b, c, d) { | |
| Parent.apply(this, arguments); | |
| } | |
| Child.prototype = new Parent; | |
| ``` | |
| Or you may write this: | |
| ```javascript | |
| function Child(a, b, c, d) { | |
| this.constructor.apply(this, arguments); | |
| } | |
| Child.prototype = new Parent; | |
| ``` | |
| The diference from the default inherited pattern is it allows for passing arguments to Child and it will call the Parent's constructor. Besides this, if there is no need to pass arguments to create the instance of Child, it is the same as the default inherited pattern. | |
| ```javascript | |
| function Child() {} | |
| Child.prototype = new Parent; | |
| ``` | |
| So the key point here is not only inherited the properties from Parent, but also renting the Parent's constructor by passing arguments to it. | |
| #### A Temporary Constructor #5 | |
| ```javascript | |
| ``` | |
| ### Further More | |
| #### Prototypal Inheritance | |
| As #1 showed, a common way to implement `inherit()` method is adding a for...in loop to it. That allows us to pass a literal object to it. Such like: | |
| `inherit(child1, child2, {/* methods here */})` | |
| Or the original way also works | |
| `inherit(child1, child2, mother = new Parent)` | |
| Here comes the function: | |
| ```javascript | |
| function inherit() { | |
| var children, module, key, i; | |
| // get list of children | |
| children = [].slice.call(arguments); | |
| // get object with extensions | |
| module = children.pop(); | |
| for ( i = children.length - 1; i >= 0; i--) { | |
| for (key in module) { | |
| children[i].prototype[key] = module[key]; | |
| } | |
| } | |
| } | |
| ``` | |
| > Note: There is no default arguments in this `inherit()` method. | |
| #### Extend Static Members | |
| Distinguish from Prototypal Inheritance, a 'shallow copy' will only copy the members to the target object, without effecting its chain inheritance. | |
| ```javascript | |
| function extend() { | |
| var children, module, key, i; | |
| // get list of children | |
| children = [].slice.call(arguments); | |
| // get object with extensions | |
| module = children.pop(); | |
| for ( i = children.length - 1; i >= 0; i--) { | |
| for (key in module) { | |
| children[key] = module[key]; | |
| } | |
| } | |
| } | |
| ``` | |
| > Note: In class-based language, like Java or C++, the set of this shallow copy is called static members. | |
| deep copy | |
| > Written with [StackEdit](https://stackedit.io/). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment