Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does 'this' inside String.prototype refer to an object type, not a string type?

I'm trying to extend string to provide a hash of itself. I am using the Node.js crypto library.

I extend string like this:

String.prototype.hashCode = function() {
    return getHash(this);
};

and I have a getHash function that looks like this:

function getHash(testString) {
    console.log("type is" + typeof(testString));
    var crypto = require('crypto');
    var hash = crypto.createHash("sha256");
    hash.update(testString);
    var result = hash.digest('hex');
    return result;
}

The function works fine when called directly, as in

var s = "Hello world";
console.log(getHash(s));

but when I try:

var s = "ABCDE";
console.log(s.hashCode());

the method call fails. It appears that this in the String.prototype.hashCode is identified as an object when crypto.hash.update is called, but a string is expected. I thought that this inside String.prototype would be the string itself, but for some reason it looks like an object to getHash(). How can I fix it?

like image 530
GGizmos Avatar asked Jan 02 '15 03:01

GGizmos


People also ask

Is a String an object in JavaScript?

In JavaScript, strings are not objects. They are primitive values. However, there exist String objects which can be used to store string values, but those String objects are not used in practice.

What is String prototype in JavaScript?

Definition and Usage The prototype is a property available with all JavaScript objects. The prototype property allows you to add new properties and methods to strings.

How do I find my prototype?

The prototype of an object is referred to by the prototype property of the constructor function that creates and initializes the object. The isPrototypeOf() method provides a way to determine if one object is the prototype of another. This technique can be used to determine the class of an object.


2 Answers

this can’t be of a primitive type outside of strict mode, so it becomes a String wrapper type, which doesn’t behave like a primitive string at all (particularly as far as typeof and equality – both strict and loose – go). You can cast it:

String.prototype.hashCode = function () {
    return getHash('' + this);
};

where '' + is used to cast any value to a primitive string. (String(this) also works, if you feel that it’s clearer.)

You can also go into strict mode, where things just make sense:

String.prototype.hashCode = function () {
    'use strict';
    return getHash(this);
};
like image 156
Ry- Avatar answered Nov 07 '22 09:11

Ry-


When you call a method on a variable of primitive type, so-called auto-boxing is taken place. That process wraps a primitive value into corresponding object, for example 'asdf' to new String('asdf'). Because technically primitive values don't have methods and properties, they are hosted in object prototypes. With auto-boxing you could call methods on primitive values. And within a method, this is always the object that has that method.

If you want to access the primitive value in a method, you could either pass it as an argument, or as you would like, retrieve primitive value from this. For example:

var str = new String('asdf') // String {0: "a", 1: "s", 2: "d", 3: "f", length: 4, formatUnicorn: function, truncate: function, splitOnLast: function, [[PrimitiveValue]]: "asdf"}
String(str) // 'asdf'

var num = new Number(123) // Number {[[PrimitiveValue]]: 123}
Number(num) // 123

var bool = new Boolean(true) // Boolean {[[PrimitiveValue]]: true}
Boolean(bool) // true
like image 36
Leo Avatar answered Nov 07 '22 08:11

Leo