A string primitive is a string literal like so:
1 |
let s = "Bob" |
However, we can also create String objects like so:
1 2 |
var a = new String("Bob"); // Object String console.log(a.indexOf('o')) // 1 |
This ‘a’ string, not a primitive. It was created using object String. Thus, when you
display it, you’ll see that it has many properties 0, 1, 2, with their values as 0: “B”, 1: “o”, 2: “b”.
Its length is 3.
StringĀ {"Bob"}
0: "B"
1: "o"
2: "b"
length: 3
__proto__: String[[PrimitiveValue]]: "Bob"
When you’re using function constructors to create Strings, Numbers, etc, you are creating Objects.
Add features to all String objects
1 2 3 4 |
String.prototype.isLengthGreaterThan = function(limit) { return this.length > limit; } new String("John").isLengthGreaterThan(2); // true |
if we invoke a function on a string literal, JS converts the string literal to a String object automatically:
1 2 |
// string literal "John" becomes new String("John") "John".isLengthGreaterThan(2); // true |
However, we can’t do this for Number objects.
1 2 3 4 5 6 7 8 9 |
Number.prototype.isGreaterThanZero = function() { return this > 0; } 3.isGreaterThanZero() // error. JS does not convert number primitives // for Number objects, we'll have to go with the function constructors new Number(3).isGreaterThanZero() // true |
Danger
For example when we use value comparison ‘==’ between primitive 3 and Number object 3, it will compare the values 3, and give you true
1 2 3 4 |
let a = 3; let b = new Number(3); a == b // true |
However, === compares values AND types. So in this case, it would give us false
1 |
a === b, //false |
Array object dangers
Because for Array objects, the indexes (0, 1, 2, …n) become properties of the Array Object. Their values would be the data in the array.
However, this presents a problem. When we use for-in to loop through arrays, it goes like this:
1 2 3 4 5 |
var arr = ['ricky', 'joy', 'En En']; for (var prop in arr) { console.log(arr[prop]); } |
print out prop, and you’ll get string type index “0”, “1”, “2”…etc. These are properties of our Array object.
However, if we were to add properties to Array prototype, it would also show.
1 2 3 4 5 6 7 |
Array.prototype.haha = "hahah"; var arr = ['ricky', 'joy', 'En En']; for (var prop in arr) { console.log(arr[prop]); } |
if you were to use the for..in loop again, you’ll see the property:
ricky
joy
En En
hahah
In order to combat this, we can use hasOwnProperty. First we have to check to see if the array’s string type indexes are its own property.
We see that it is. Our haha propety belongs to the prototype object, and not of the array object itself:
1 2 3 4 5 |
console.log(arr.hasOwnProperty("0")); // true console.log(arr.hasOwnProperty("1")); // true console.log(arr.hasOwnProperty("2")); // true console.log(arr.hasOwnProperty("3")); // FALSE console.log(arr.hasOwnProperty("haha")); // FALSE |
Thus, when using for..in, you’ll have to add a check to display if the property is the object’s own.
1 2 3 4 5 |
for (var prop in arr) { if (arr.hasOwnProperty(prop)) { console.log(arr[prop]); } } |
…or you can also simply use the original for loop like so
1 2 3 |
for (let i = 0; i < arr.length; i++ ) { console.log(arr[i]); } |