Reputation: 1877
How prototype property can be used with string variable in JavaScript. There is topic in our textbook which shows prototype as property but lack of explanations and confusing about it's usage
Take this code example for reference.
let x = 'stackoverflow';
console.log(x.prototype) // gives list of functions
console.log(x.prototype.toLowerCase())) // gives error
Upvotes: 0
Views: 96
Reputation: 1074238
The String.prototype
object is what gives strings their methods (even though most strings you deal with are primitives, not objects). If there weren't a String.prototype.toLowerCase
function, then "FOO".toLowerCase()
wouldn't work. This is the fundamental prototypical nature of JavaScript (but a bit confusing, with most strings being primitives; more on that below¹).
One use of String.prototype
in userland code is to add methods to strings:
Object.defineProperty(String.prototype, "initialCaps", {
writable: true,
configurable: true,
value() {
return this.charAt(0).toUpperCase() + this.slice(1);
}
});
console.log("testing".initialCaps());
In general, extending built-in prototypes like that is best avoided in library or framework code because of the possibility of conflicts with other libraries, etc. It's generally okay in your own app or web page code, though.
A couple of best practices rules if you do that:
Make sure the methods you add are non-enumerable by using Object.defineProperty
as in the example above. don't just do String.prototype.initialCaps = function() { /*...*/ };
, that creates an enumerable property. Because the example above doesn't say enumerable: true
, the property is non-enumerable by default. (Builtin methods are typically writable and configurable, though.)
Use names that are unlikely to be used by future additions to JavaScript, so they don't conflict later if things are added.
Never extend Object.prototype
if you're using any third-party code. You may break that code.
Be cautious extending Array.prototype
if you're using any third-party code. You may break that code.
With thorough testing you could of course go against any of those, but...
¹ About the primitive string vs. string object thing:
"example"
creates a primitive string. Primitives aren't objects (in theory) and so they don't have properties or methods (in theory). But most primitives have an object constructor associated with them: String
is the case of strings, Number
for numbers, etc. (null
and undefined
do not have associated constructors.) If you try to use a property or method on a primitive with an associated constructor function, in theory the JavaScript engine creates an object equivalent of that primitive and then does the property/method lookup on that object. Since that object's prototype is the object from the prototype
property on its constructor, it gets properties and methods from that object. If it's a method, the JavaScript engine calls the method with the original primitive value as this
. (In loose mode, it'll get converted to object so this
is an object within the call; in strict mode, though, this
can be a primitive, and is in the case of method calls on a primitive.)
All of which is a long way of explaining that "example".toLowerCase()
ends up calling String.prototype.toLowerCase
with this
set to "example"
.
I said "in theory" a couple of times above because JavaScript engines do a lot of optimization. As long as they behave in line with what the spec says, they don't have to literally do what the spec says. You can be fairly sure that when you do "example".length
or "example".toLowerCase()
(for instance), no modern JavaScript engine actually creates a String
object under the covers for any of the built-in object properties/methods. (It may have to if you've added any, if your additions are in loose mode. One of many reasons to always use strict mode.)
Upvotes: 2