Explore JavaScript's built-in constructors like Object, Array, Function, and Date, and learn how to extend their prototypes responsibly.
In this section, we will delve into JavaScript’s built-in constructors and their prototypes. Understanding these concepts is crucial for anyone looking to master object-oriented programming in JavaScript. We will explore common built-in constructors, how they can be extended, and the best practices for doing so responsibly.
JavaScript provides a set of built-in constructors that allow us to create objects of various types. These constructors are functions that, when invoked with the new
keyword, create and return an object. Some of the most common built-in constructors include:
Each of these constructors has an associated prototype object. When a new object is created using a constructor, it inherits properties and methods from the constructor’s prototype.
In JavaScript, every function, including constructors, has a prototype
property. This property is an object that contains properties and methods that should be shared by all instances created by the constructor. When you create a new object using a constructor, JavaScript sets the object’s internal [[Prototype]]
(also known as __proto__
) to point to the constructor’s prototype
object.
Let’s visualize how the prototype chain works using a simple diagram:
graph TD; A[Array Constructor] --> B[Array Prototype] B --> C[Array Instance] D[Object Constructor] --> E[Object Prototype] E --> C
In this diagram, an array instance inherits from the Array Prototype
, which in turn inherits from the Object Prototype
. This chain is what allows JavaScript objects to have access to methods and properties defined higher up in the chain.
Let’s take a closer look at some of the most commonly used built-in constructors in JavaScript.
The Object
constructor is the most basic constructor in JavaScript. It is used to create plain objects:
let obj = new Object();
console.log(obj); // Outputs: {}
However, in practice, object literals {}
are more commonly used to create objects.
The Array
constructor is used to create array objects:
let arr = new Array(1, 2, 3);
console.log(arr); // Outputs: [1, 2, 3]
Again, array literals []
are more commonly used in practice.
The Function
constructor creates new function objects:
let func = new Function('a', 'b', 'return a + b');
console.log(func(2, 3)); // Outputs: 5
However, function expressions or declarations are preferred for creating functions.
The Date
constructor creates date objects:
let date = new Date();
console.log(date); // Outputs: current date and time
These constructors create wrapper objects for primitive values:
let str = new String('Hello');
let num = new Number(42);
let bool = new Boolean(true);
console.log(str); // Outputs: [String: 'Hello']
console.log(num); // Outputs: [Number: 42]
console.log(bool); // Outputs: [Boolean: true]
JavaScript allows us to extend the prototypes of built-in constructors by adding new methods or properties. This can be useful for adding functionality that is not available by default. However, it must be done with caution to avoid potential issues.
Let’s add a method to the Array
prototype:
Array.prototype.last = function() {
return this[this.length - 1];
};
let numbers = [1, 2, 3];
console.log(numbers.last()); // Outputs: 3
In this example, we added a last
method to the Array
prototype, which returns the last element of the array.
While extending built-in prototypes can be powerful, it comes with risks:
Let’s explore some practical examples of extending built-in prototypes responsibly.
Suppose we want to add a method to the String
prototype that repeats a string a specified number of times:
String.prototype.repeatString = function(count) {
return this.repeat(count);
};
let greeting = 'Hello';
console.log(greeting.repeatString(3)); // Outputs: HelloHelloHello
In this example, we added a repeatString
method to the String
prototype, which uses the built-in repeat
method to repeat the string.
Let’s add a method to the Date
prototype that formats the date as YYYY-MM-DD
:
Date.prototype.toFormattedString = function() {
let year = this.getFullYear();
let month = (this.getMonth() + 1).toString().padStart(2, '0');
let day = this.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
};
let today = new Date();
console.log(today.toFormattedString()); // Outputs: formatted date
In this example, we added a toFormattedString
method to the Date
prototype, which formats the date in a specific format.
Now it’s your turn! Try modifying the code examples above to add your own methods to built-in prototypes. For instance, you could add a method to the Array
prototype that returns the sum of all elements in the array. Remember to follow best practices and use unique method names.
Before we wrap up, let’s do a quick knowledge check to reinforce what we’ve learned.
In this section, we’ve explored JavaScript’s built-in constructors and their prototypes. We’ve learned how to extend these prototypes by adding new methods and discussed the risks and best practices associated with doing so. By understanding these concepts, you can harness the power of JavaScript’s object-oriented features while writing clean and maintainable code.
Remember, this is just the beginning. As you progress, you’ll build more complex and interactive web pages. Keep experimenting, stay curious, and enjoy the journey!