Instantiating Constructors Using the new
Operator
A constructor function is basically a cookie-cutter template used to create pre-configured objects. Take String()
for example. This function, when used with thenew
operator (new String('foo')
), creates a string instance based on theString()
"template.” Let's look at an example.
Sample: sample9.html
1
2
3
4
5
6
7
<!DOCTYPE html><html lang=
"en"
><body><script>
var
myString =
new
String(
'foo'
);
console.log(myString);
// Logs foo {0 = "f", 1 = "o", 2 = "o"}
</script></body></html>
In this snippet, we created a new string object that is an instance of the String()
constructor function. Just like that, we have a string value expressed in JavaScript.
I'm not suggesting that you use constructor functions instead of their literal/primitive equivalentslike var string="foo";
. I am, however, suggesting that you understand what is going on behind literal/primitive values.
As previously mentioned, the JavaScript language has the following native predefined constructors: Number()
, String()
, Boolean()
, Object()
, Array()
, Function()
,Date()
, RegExp()
, and Error()
. We can instantiate an object instance from any of these constructor functions by applying the new operator. In the following sample, I construct these nine native JavaScript objects.
Sample: sample10.html
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html><html lang=
"en"
><body><script>
// Instantiate an instance for each native constructor using the new keyword.
var
myNumber =
new
Number(23);
var
myString =
new
String(
'male'
);
var
myBoolean =
new
Boolean(
false
);
var
myObject =
new
Object();
var
myArray =
new
Array(
'foo'
,
'bar'
);
var
myFunction =
new
Function(
"x"
,
"y"
,
"return x*y"
);
var
myDate =
new
Date();
var
myRegExp =
new
RegExp(
'\bt[a-z]+\b'
);
var
myError =
new
Error(
'Darn!'
);
// Log/verify which constructor created the object.
console.log(myNumber.constructor);
// Logs Number()
console.log(myString.constructor);
// Logs String()
console.log(myBoolean.constructor);
// Logs Boolean()
console.log(myObject.constructor);
// Logs Object()
console.log(myArray.constructor);
// Logs Array() in modern browsers.
console.log(myFunction.constructor);
// Logs Function()
console.log(myDate.constructor);
// Logs Date()
console.log(myRegExp.constructor);
// Logs RegExp()
console.log(myError.constructor);
// Logs Error()
</script></body></html>
By using the new
operator, we are telling the JavaScript interpreter that we would like an object that is an instance of the corresponding constructor function. For example, in the code sample, the Date()
constructor function is used to create date objects. TheDate()
constructor function is a cookie cutter for date objects. That is, it produces date objects from a default pattern defined by the Date()
constructor function.
At this point, you should be well acquainted with creating object instances from native constructor functions (e.g., new String('foo')
) and user-defined constructor functions (e.g, new Person(true, 33, 'male')
).
Keep in mind that Math
is a static objecta container for other methodsand is not a constructor that uses the new
operator.
String()
for example. This function, when used with thenew
operator (new String('foo')
), creates a string instance based on theString()
"template.” Let's look at an example.
1
2
3
4
5
6
7
| <!DOCTYPE html><html lang= "en" ><body><script> var myString = new String( 'foo' ); console.log(myString); // Logs foo {0 = "f", 1 = "o", 2 = "o"} </script></body></html> |
String()
constructor function. Just like that, we have a string value expressed in JavaScript.var string="foo";
. I am, however, suggesting that you understand what is going on behind literal/primitive values.Number()
, String()
, Boolean()
, Object()
, Array()
, Function()
,Date()
, RegExp()
, and Error()
. We can instantiate an object instance from any of these constructor functions by applying the new operator. In the following sample, I construct these nine native JavaScript objects.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| <!DOCTYPE html><html lang= "en" ><body><script> // Instantiate an instance for each native constructor using the new keyword. var myNumber = new Number(23); var myString = new String( 'male' ); var myBoolean = new Boolean( false ); var myObject = new Object(); var myArray = new Array( 'foo' , 'bar' ); var myFunction = new Function( "x" , "y" , "return x*y" ); var myDate = new Date(); var myRegExp = new RegExp( '\bt[a-z]+\b' ); var myError = new Error( 'Darn!' ); // Log/verify which constructor created the object. console.log(myNumber.constructor); // Logs Number() console.log(myString.constructor); // Logs String() console.log(myBoolean.constructor); // Logs Boolean() console.log(myObject.constructor); // Logs Object() console.log(myArray.constructor); // Logs Array() in modern browsers. console.log(myFunction.constructor); // Logs Function() console.log(myDate.constructor); // Logs Date() console.log(myRegExp.constructor); // Logs RegExp() console.log(myError.constructor); // Logs Error() </script></body></html> |
new
operator, we are telling the JavaScript interpreter that we would like an object that is an instance of the corresponding constructor function. For example, in the code sample, the Date()
constructor function is used to create date objects. TheDate()
constructor function is a cookie cutter for date objects. That is, it produces date objects from a default pattern defined by the Date()
constructor function.new String('foo')
) and user-defined constructor functions (e.g, new Person(true, 33, 'male')
).Math
is a static objecta container for other methodsand is not a constructor that uses the new
operator.Creating Shorthand or Literal Values from Constructors
JavaScript provides shortcutscalled "literals" for manufacturing most of the native object values without having to use new Foo()
or new Bar()
. For the most part, the literal syntax accomplishes the same thing as using the new
operator. The exceptions are:Number()
, String()
, and Boolean()
see the notes after the following sample.
If you come from other programming backgrounds, you are likely more familiar with the literal way of creating objects. In the following sample, I instantiate the native JavaScript constructors using the new
operator and then create corresponding literal equivalents.
Sample: sample11.html
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html><html lang=
"en"
><body><script>
var
myNumber =
new
Number(23);
// An object.
var
myNumberLiteral = 23;
// Primitive number value, not an object.
var
myString =
new
String(
'male'
);
// An object.
var
myStringLiteral =
'male'
;
// Primitive string value, not an object.
var
myBoolean =
new
Boolean(
false
);
// An object.
var
myBooleanLiteral =
false
;
// Primitive boolean value, not an object.
var
myObject =
new
Object();
var
myObjectLiteral = {};
var
myArray =
new
Array(
'foo'
,
'bar'
);
var
myArrayLiteral = [
'foo'
,
'bar'
];
var
myFunction =
new
Function(
"x"
,
"y"
,
"return x*y"
);
var
myFunctionLiteral =
function
(x, y) {
return
x * y };
var
myRegExp =
new
RegExp(
'\bt[a-z]+\b'
);
var
myRegExpLiteral = /\bt[a-z]+\b/;
// Verify that literals are created from same constructor.
console.log(myNumber.constructor, myNumberLiteral.constructor);
console.log(myString.constructor, myStringLiteral.constructor);
console.log(myBoolean.constructor, myBooleanLiteral.constructor);
console.log(myObject.constructor, myObjectLiteral.constructor);
console.log(myArray.constructor, myArrayLiteral.constructor);
console.log(myFunction.constructor, myFunctionLiteral.constructor);
console.log(myRegExp.constructor, myRegExpLiteral.constructor);
</script></body></html>
What you need to take away here is the fact that, in general, using literals simply conceals the underlying process identical to using the new
operator. Maybe more importantly, its much more convenient!
Okay, things are a little more complicated with respect to the primitive string, number, and Boolean values. In these cases, literal values take on the characteristics of primitive values rather than complex object values. See the notes that follow.
When using literal values for String()
, Number()
, and Boolean()
, an actual complex object is never created until the value is treated as an object. In other words, you are dealing with a primitive data type until you attempt to use methods or retrieve properties associated with the constructor (e.g., var charactersInFoo = 'foo'.length
). When this happens, JavaScript creates a wrapper object for the literal value behind the scenes, allowing the value to be treated as an object. Then, after the method is called, JavaScript discards the wrapper object and the value returns to a literal type. This is why string, number, and Boolean are considered primitive (or simple) data types. I hope this clarifies the misconception "everything in JavaScript is an object" from the concept "everything in JavaScript can act like an object.”
new Foo()
or new Bar()
. For the most part, the literal syntax accomplishes the same thing as using the new
operator. The exceptions are:Number()
, String()
, and Boolean()
see the notes after the following sample.new
operator and then create corresponding literal equivalents.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| <!DOCTYPE html><html lang= "en" ><body><script> var myNumber = new Number(23); // An object. var myNumberLiteral = 23; // Primitive number value, not an object. var myString = new String( 'male' ); // An object. var myStringLiteral = 'male' ; // Primitive string value, not an object. var myBoolean = new Boolean( false ); // An object. var myBooleanLiteral = false ; // Primitive boolean value, not an object. var myObject = new Object(); var myObjectLiteral = {}; var myArray = new Array( 'foo' , 'bar' ); var myArrayLiteral = [ 'foo' , 'bar' ]; var myFunction = new Function( "x" , "y" , "return x*y" ); var myFunctionLiteral = function (x, y) { return x * y }; var myRegExp = new RegExp( '\bt[a-z]+\b' ); var myRegExpLiteral = /\bt[a-z]+\b/; // Verify that literals are created from same constructor. console.log(myNumber.constructor, myNumberLiteral.constructor); console.log(myString.constructor, myStringLiteral.constructor); console.log(myBoolean.constructor, myBooleanLiteral.constructor); console.log(myObject.constructor, myObjectLiteral.constructor); console.log(myArray.constructor, myArrayLiteral.constructor); console.log(myFunction.constructor, myFunctionLiteral.constructor); console.log(myRegExp.constructor, myRegExpLiteral.constructor); </script></body></html> |
new
operator. Maybe more importantly, its much more convenient!String()
, Number()
, and Boolean()
, an actual complex object is never created until the value is treated as an object. In other words, you are dealing with a primitive data type until you attempt to use methods or retrieve properties associated with the constructor (e.g., var charactersInFoo = 'foo'.length
). When this happens, JavaScript creates a wrapper object for the literal value behind the scenes, allowing the value to be treated as an object. Then, after the method is called, JavaScript discards the wrapper object and the value returns to a literal type. This is why string, number, and Boolean are considered primitive (or simple) data types. I hope this clarifies the misconception "everything in JavaScript is an object" from the concept "everything in JavaScript can act like an object.”Primitive (aka Simple) Values
The JavaScript values 5, 'foo', true
, and false
, as well as null
and undefined
, are considered primitive because they are irreducible. That is, a number is a number, a string is a string, a Boolean is either true
or false
, and null
and undefined
are just that, null
and undefined
. These values are inherently simple and do not represent values that can be made up of other values.
Examine the following code and ask yourself if the string, number, Boolean, null
, andundefined
values could be more complex. Contrast this to what you know of anObject()
instance, Array()
instance, or really any complex object.
Sample: sample12.html
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html><html lang=
"en"
><body><script>
var
myString =
'string'
var
myNumber = 10;
var
myBoolean =
false
;
// Could be true or false, but that is it.
var
myNull =
null
;
var
myUndefined = undefined;
console.log(myString, myNumber, myBoolean, myNull, myUndefined);
/* Consider that a complex object like array or object can be made up of multiple primitive values, and thus becomes a complex set of multiple values. */
var
myObject = {
myString:
'string'
,
myNumber: 10,
myBoolean:
false
,
myNull:
null
,
myUndefined: undefined
};
console.log(myObject);
var
myArray = [
'string'
, 10,
false
,
null
, undefined];
console.log(myArray);
</script></body></html>
Quite simply, primitive values represent the lowest form (i.e. simplest) of data and information available in JavaScript.
As opposed to creating values with literal syntax, when a String()
, Number()
, orBoolean()
value is created using the new keyword, the object created is actually a complex object.
Its critical that you understand the fact that the String()
, Number()
, and Boolean()
constructors are dual-purpose constructors used to create literal/primitive values as well as complex values. These constructors do not always return objects, but instead, when used without the "new
" operator, can return a primitive representation of the actual complex object value.
true
, and false
, as well as null
and undefined
, are considered primitive because they are irreducible. That is, a number is a number, a string is a string, a Boolean is either true
or false
, and null
and undefined
are just that, null
and undefined
. These values are inherently simple and do not represent values that can be made up of other values.null
, andundefined
values could be more complex. Contrast this to what you know of anObject()
instance, Array()
instance, or really any complex object.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| <!DOCTYPE html><html lang= "en" ><body><script> var myString = 'string' var myNumber = 10; var myBoolean = false ; // Could be true or false, but that is it. var myNull = null ; var myUndefined = undefined; console.log(myString, myNumber, myBoolean, myNull, myUndefined); /* Consider that a complex object like array or object can be made up of multiple primitive values, and thus becomes a complex set of multiple values. */ var myObject = { myString: 'string' , myNumber: 10, myBoolean: false , myNull: null , myUndefined: undefined }; console.log(myObject); var myArray = [ 'string' , 10, false , null , undefined]; console.log(myArray); </script></body></html> |
String()
, Number()
, orBoolean()
value is created using the new keyword, the object created is actually a complex object.String()
, Number()
, and Boolean()
constructors are dual-purpose constructors used to create literal/primitive values as well as complex values. These constructors do not always return objects, but instead, when used without the "new
" operator, can return a primitive representation of the actual complex object value.Primitive Values Are Not Objects
The null
and undefined
values are such trivial values that they do not require a constructor function, nor the use of the new
operator to establish them as a JavaScript value. To use null
or undefined
, all you do is use them as if they were an operator. The remaining primitive valuesstring, number, and Booleanwhile technically returned from a constructor function, are not objects.
In the following sample, I contrast the difference between primitive values and the rest of the native JavaScript objects.
Sample: sample13.html
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html><html lang=
"en"
><body><script>
// No object is created when producing primitive values; notice no use of the "new" keyword.
var
primitiveString1 =
"foo"
;
var
primitiveString2 = String(
'foo'
);
var
primitiveNumber1 = 10;
var
primitiveNumber2 = Number(
'10'
);
var
primitiveBoolean1 =
true
;
var
primitiveBoolean2 = Boolean(
'true'
);
// Confirm the typeof is not object.
console.log(
typeof
primitiveString1,
typeof
primitiveString2);
// Logs 'string,string'.
console.log(
typeof
primitiveNumber1,
typeof
primitiveNumber2);
// Logs 'number,number'.
console.log(
typeof
primitiveBoolean1,
typeof
primitiveBoolean2);
// Logs 'Boolean,Boolean'.
// Using a constructor and the "new" keyword for creating objects.
var
myNumber =
new
Number(23);
var
myString =
new
String(
'male'
);
var
myBoolean =
new
Boolean(
false
);
var
myObject =
new
Object();
var
myArray =
new
Array(
'foo'
,
'bar'
);
var
myFunction =
new
Function(
"x"
,
"y"
,
"return x * y"
);
var
myDate =
new
Date();
var
myRegExp =
new
RegExp(
'\\bt[a-z]+\\b'
);
var
myError =
new
Error(
'Darn!'
);
// Logs 'object object object object object function object function object'.
console.log(
typeof
myNumber,
typeof
myString,
typeof
myBoolean,
typeof
myObject,
typeof
myArray,
typeof
myFunction,
// BE AWARE typeof returns function for all function objects.
typeof
myDate,
typeof
myRegExp,
// BE AWARE typeof returns function for RegExp()
typeof
myError
);
</script></body></html>
What I would like you to learn from the previous code example is that primitive values are not objects. Primitive values are special in that they are used to represent simple values.
null
and undefined
values are such trivial values that they do not require a constructor function, nor the use of the new
operator to establish them as a JavaScript value. To use null
or undefined
, all you do is use them as if they were an operator. The remaining primitive valuesstring, number, and Booleanwhile technically returned from a constructor function, are not objects.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| <!DOCTYPE html><html lang= "en" ><body><script> // No object is created when producing primitive values; notice no use of the "new" keyword. var primitiveString1 = "foo" ; var primitiveString2 = String( 'foo' ); var primitiveNumber1 = 10; var primitiveNumber2 = Number( '10' ); var primitiveBoolean1 = true ; var primitiveBoolean2 = Boolean( 'true' ); // Confirm the typeof is not object. console.log( typeof primitiveString1, typeof primitiveString2); // Logs 'string,string'. console.log( typeof primitiveNumber1, typeof primitiveNumber2); // Logs 'number,number'. console.log( typeof primitiveBoolean1, typeof primitiveBoolean2); // Logs 'Boolean,Boolean'. // Using a constructor and the "new" keyword for creating objects. var myNumber = new Number(23); var myString = new String( 'male' ); var myBoolean = new Boolean( false ); var myObject = new Object(); var myArray = new Array( 'foo' , 'bar' ); var myFunction = new Function( "x" , "y" , "return x * y" ); var myDate = new Date(); var myRegExp = new RegExp( '\\bt[a-z]+\\b' ); var myError = new Error( 'Darn!' ); // Logs 'object object object object object function object function object'. console.log( typeof myNumber, typeof myString, typeof myBoolean, typeof myObject, typeof myArray, typeof myFunction, // BE AWARE typeof returns function for all function objects. typeof myDate, typeof myRegExp, // BE AWARE typeof returns function for RegExp() typeof myError ); </script></body></html> |
How Primitive Values Are Stored/Copied in JavaScript
It is extremely important to understand that primitive values are stored and manipulated at "face value. It might sound simple, but this means that if I store the string value "foo" in a variable called myString
, then the value "foo" is literally stored in memory as such. Why is this important? Once you begin manipulating (e.g., copying) values, you have to be equipped with this knowledge, because primitive values are copied literally.
In the following example, we store a copy of the myString
value ('foo')
in the variable myStringCopy, and its value is literally copied. Even if we change the original value, the copied value, referenced by the variable myStringCopy
, remains unchanged.
Sample: sample14.html
01
02
03
04
05
06
07
08
09
10
11
<!DOCTYPE html><html lang=
"en"
><body><script>
var
myString =
'foo'
// Create a primitive string object.
var
myStringCopy = myString;
// Copy its value into a new variable.
var
myString =
null
;
// Manipulate the value stored in the myString variable.
/*The original value from myString was copied to myStringCopy. This is confirmed by updating the value of myString then checking the value of myStringCopy.*/
console.log(myString, myStringCopy);
// Logs 'null foo'
</script></body></html>
The concept to take away here is that primitive values are stored and manipulated as irreducible values. Referring to them transfers their value. In the previous example, we copied, or cloned, the myString
value to the variable myStringCopy
. When we updated the myString
value, the myStringCopy
value still had a copy of the oldmyString
value. Remember this and contrast the mechanics here with complex objects (discussed in the following section).
myString
, then the value "foo" is literally stored in memory as such. Why is this important? Once you begin manipulating (e.g., copying) values, you have to be equipped with this knowledge, because primitive values are copied literally.myString
value ('foo')
in the variable myStringCopy, and its value is literally copied. Even if we change the original value, the copied value, referenced by the variable myStringCopy
, remains unchanged.
01
02
03
04
05
06
07
08
09
10
11
| <!DOCTYPE html><html lang= "en" ><body><script> var myString = 'foo' // Create a primitive string object. var myStringCopy = myString; // Copy its value into a new variable. var myString = null ; // Manipulate the value stored in the myString variable. /*The original value from myString was copied to myStringCopy. This is confirmed by updating the value of myString then checking the value of myStringCopy.*/ console.log(myString, myStringCopy); // Logs 'null foo' </script></body></html> |
myString
value to the variable myStringCopy
. When we updated the myString
value, the myStringCopy
value still had a copy of the oldmyString
value. Remember this and contrast the mechanics here with complex objects (discussed in the following section).
No comments:
Post a Comment