
3.5.1. Extending native object prototypes such as `Array.prototype` and `String.prototype`
The operation of extending prototypes must be performed with caution due to several potential risks.
There are alternatives to perform this task without resorting to extending native prototypes.
3.5.2. Explanation of why modifying native prototypes can be dangerous
Potential risks
a) Unexpected behavior
b) Conflicts with libraries
c) Difficulty debugging
d) Loss of compatibility
e) Security issues
3.6. `hasOwnProperty()`, `in`, and `for...in`
3.6.1. Correct use of `hasOwnProperty()`
3.6.2. Correct use of in
Example 1
3.6.3. Correct use of for...in
Example 1
3.6.4. Comparison between `for...in` and `Object.keys()`
Example 1. Iterating over all properties with for…in
Example 2 Iterating over own properties with Object.keys() (does not include inherited ones)
3.7. Prototypes in class (ES6+)
3.7.1. Explanation of how ES6 classes use prototypes under the hood.
Example 1. Invoking hidden prototypes.
3.7.2. Comparison between classes and constructor functions
3.7.2.1. Constructor Functions
See 2.3.1.2 Object Creation using Constructor Functions
Example 1. Object creation using constructor functions
3.7.2.2. Classes. Let's transform the previous constructor function into a class.
Example 2. Converting the Fulano constructor function into a class
3.7.2.3. Extending the previous class, adding a new method and a new property
Example 1. Adding a new method to the Fulanito class
Example 2. Extending the previous class with a new subclass and adding a new property
3.8.1 Prototype Pattern
Example 1. Prototype Pattern in JavaScript.
3.8.2 Factory Pattern:
Example 1. Different access levels
3.8.3 Singleton Pattern.
Example 1 Singleton pattern in JavaScript.
3.8.4 Builder Pattern
Example 1. Creational Builder Pattern.
3.9 Using Mixins to share functionalities between objects
Example 1. Application of Mixins
3.10. Best Practices and Considerations
3.10.1. Memory usage optimization through prototypal inheritance.
Example 1 Excessive memory usage
Example 2 Reusing code to increase memory performance
Example 3 Measuring the performance of each function
Time to generate 1 million objects with the crearExcesivo() function
Time to generate the object with the reutilizar() function
Time difference and ratio in object creation between both functions.
The ratio between both solutions is
In the first exercise (3.10.1 - 3.1), 1 million objects are generated
using the crearExcesivo() function.
The creation time for each object is lower compared
to the second exercise, where a single object is created containing
1 million objects using the reutilizar() function.
Although creating objects with crearExcesivo() is faster,
it requires 1 million clusters to store all created objects.
On the other hand, by using the reutilizar() function, a single object
is generated that stores 1 million objects, thus occupying less memory space.
In summary, the higher the object generation speed,
the higher the memory consumption.
3.11.1 Inheritance vs Composition
Example 1. Using Inheritance.
Example 2. Using Composition. There is a relationship type: "an object has a specification"
When to Use Inheritance vs Composition
a) Use Inheritance when there is a clear "is-a" relationship.
In the previous Example 1, an Animal is a Bird or a Fish.
b) Use Composition when:
There is a "has-a" relationship or you need to combine behaviors.
In the previous Example 2, an animal has behaviors such as walking, flying, running, etc.
3.11.2 Use Inheritance when there is a clear "is-a" relationship.
Example 1: Using Inheritance. A Product is an Article
3.11.3 Use Composition when there is a "has-a characteristic" relationship.
Example 1: Using Composition. A Product has a characteristic.
In the example, we create specific functions to handle characteristics.
3.12.1 Create an object hierarchy using prototypal inheritance.
Responsive Modular Web Page Project
Prototypal inheritance in JavaScript allows for the creation of an object hierarchy
where objects can inherit properties and methods from other objects.
We will implement an example of prototypal inheritance to manage the
construction of a modular web page (10-03proto_index.html) that
links external components such as 10-03proto_header.html, 10-03proto_style.css,
10-03proto_article.html, 10-03proto_footer.html, and 10-03proto_app.js.
Prototypal inheritance will be used to create a base structure
that allows modularizing and reusing the necessary methods and properties
to create and assemble the page.
Implementation Code Description
a) Prototypal Inheritance: Base Class
The base class Pagina handles the structure and shared methods between components.
b) Prototypal Inheritance: Derived Class
We create a derived class PaginaModular, which extends the functionality
of Pagina to include specific components.
c) Using Classes to Create the Page
We create the page 10-03proto_index.html by assembling the components and generating the HTML.
d) External Component Content
- 1. 10-03proto_header.html
- 2. 10-03proto_article.html
- 3. 10-03proto_footer.html
- 4. 10-03proto_style.css
- 5. 10-03proto_app.js
e) The Result.
When we run the code in app.js, the
10-03proto_index.html file is generated dynamically.
f) Notes on Prototypal Inheritance Implementation
- PaginaModular.
Extends Pagina's functionality through Object.create,
ensuring that shared methods are available.
- Modularity
Components (header.html, article.html, etc.) are completely separate,
making them easy to maintain, update, and reuse.
- Scalability
We can add more components, styles, or scripts simply
by extending PaginaModular.
- Dynamism
This approach allows for generating pages dynamically based
on required components, making the system more flexible.