String vs new String

G

Grant Wagner

I'm a bit confused by String() (typeof 'string') vs new String() (typeof
'object'). When you need to access a method or property of a -String-,
what type is JavaScript expecting (or rather, what should you provide),
a -String object- or a -string-?

Given the following benchmark:

var t = (new Date()).getTime();
for (var ii = 0; ii < 100000; ++ii) {
var x = (String('hi')).charAt(0); // typeof 'string'
}
document.write(((new Date()).getTime() - t) + '<br>');

var t = (new Date()).getTime();
for (var ii = 0; ii < 100000; ++ii) {
var x = (new String('hi')).charAt(0); // typeof 'object'
}
document.write(((new Date()).getTime() - t) + '<br>');

Internet Explorer is consistently faster when you apply a string method
to a -String()- than a -new String()-, yet most other browsers are
consistently only slightly slower applying a method to a -String()-.
This implies to me that JavaScript in most browsers needs to take
a -string- and wrap it in a -String object- before applying the method.

Anyway, the question isn't really about performance, it's more about
proper design. Which is "more correct"?

// avoid errors for non-string types
(String(unknownType)).replace(/something/, 'somethingElse')
(new String(unknownType)).replace(/something/, 'somethingElse')

Given that methods of String seem to return a -string- rather than
a -String object- and you can chain method calls together
(String(s)).replace(...).replace(...).replace(...) it just seems that
for "consistency" it's better to call your first String method on
a -string- rather than a -String object-.

Not to mention I have several functions which include code such as:

if ('string' == typeof s) {
if (/* some test on s */) return true;
}
return false;

and obviously these produce the wrong results when someone creates a
String object with new String() and passes it to my function. So I end
up refactoring the function to do something like:

if (null != s) {
if ('string' != typeof s) {
s = String(s); // s.toString() ?
}
if (/* some test on s */) return true;
}
return false;

It just all feels horribly cumbersome.
 
M

Martin Honnen

Grant said:
I'm a bit confused by String() (typeof 'string') vs new String() (typeof
'object'). When you need to access a method or property of a -String-,
what type is JavaScript expecting (or rather, what should you provide),
a -String object- or a -string-?
Anyway, the question isn't really about performance, it's more about
proper design. Which is "more correct"?

In my view you should always work with primitive string values so use
string literals where you want to create strings or use
String(expression) where you need to convert other values to primitive
string values. There is no need and no advantage in explictly creating
String object instances in your script, if a method needs to be applied
to a primitive string value the script engine will do all that is
necessary under the hood.
On the other hand if you would use String object instances you need to
be aware that you are dealing with objects where comparison is on object
identity so with

var s = 'Kibology';
new String(s) == new String(s)

the comparison yields false which is much different to the primitive
string value comparison.
 
M

Michael Winter

I'm a bit confused by String() (typeof 'string') vs new String() (typeof
'object'). When you need to access a method or property of a -String-,
what type is JavaScript expecting (or rather, what should you provide),
a -String object- or a -string-?

It doesn't really matter as far as the language is concerned. When a
member expression (identifier.identifier, or identifier[expression]) is
evaluated, the internal ToObject function is called on the left-hand
operand. For the built-in types, boolean, string, and number, this is
the same as creating a new object via the type's constructor function. So,

var value = 10,
string;

string = value.toString(16);

is functionally equivalent to:

string = (new Number(10)).toString(16);

In principle, it's more efficient for you to create the object yourself
if you're going to call a method several times using the same value.
But, if the value changes between each invocation, you may as well let
the engine perform the conversion for you as the built-in objects are
immutable so a new object is needed every time anyway.
[...] I end up refactoring the function to do something like:

if (null != s) {
if ('string' != typeof s) {
s = String(s); // s.toString() ?
}
if (/* some test on s */) return true;
}
return false;

I suppose it depends on what you're doing. Sometimes I write functions
that expect either an object or a string. The former is meant to be an
element reference, whereas the latter is the id of some element - a bit
of convenience for the caller. In that situation, if an object had a
toString value that represented the id, then I'd leave it to the caller
to call toString, or use String as a function.

Mike
 
V

VK

You are a bit confused about primitive values and primitive value
wrappers.

var Str = "Something";
creates a primitive value of type "string" (so it's typeof string)

var oStr = new String("Something")
creates an object using String class as its constructor (so its typeof
"object" and oStr.constructor = function String() {[native code]} ).

In the latter case the value itself becomes just one of properties of
this object: you need to use oStr.toSource() to get it.

It is ALWAYS more performance/resource effective to use primitives
rather than object wrappers.

The only reason to use object wrappers Object(), Boolean(), Number()
and String() would be to create customized objects with extra
properties and methods.
 
G

Grant Wagner

Grant Wagner said:
I'm a bit confused by String() (typeof 'string') vs new String()
(typeof 'object'). When you need to access a method or property of
a -String-, what type is JavaScript expecting (or rather, what should
you provide), a -String object- or a -string-?

Thanks for the various replies, it confirms mostly what I already knew
(that it doesn't matter much). I mostly just wanted to hear peoples'
reasoning on one choice or another.
 
G

Grant Wagner

VK said:
You are a bit confused about primitive values and primitive value
wrappers.

No I'm not. My question was basically: Since the underlying
implementation, when confronted with "string".charAt(0); converts this
to new String("string").charAt(0); is it better to do this yourself in
advance as a matter of design (without regard for performance)?
It is ALWAYS more performance/resource effective to use primitives
rather than object wrappers.

No it isn't. As I've shown, in most Web browsers it is more performant
(by a neligible margin) to wrap a string in a String object yourself
before calling a String.prototype method on it.

var s = 'test string';
var t = (new Date()).getTime();
for (var ii = 0; ii < 100000; ++ii) {
var x = s.charAt(0); // typeof 'string'
}
document.write(((new Date()).getTime() - t) + '<br>');
var t = (new Date()).getTime();
for (var ii = 0; ii < 100000; ++ii) {
var x = (new String(s)).charAt(0); // typeof 'object'
}
document.write(((new Date()).getTime() - t) + '<br>');

In Firefox 1.0.4, Mozilla 1.7.8 and Netscape 4.78 (reduced loop counts
from 100000 to 10000) the second test (where I wrap the string in a
String object before invoking charAt() on it) has a slight (very slight)
advantage.

In Mozilla 1.0.2 and Opera 6.05, 7.54u2 and 8.00 the first test (where I
let the underlying implementation wrap it in a String object) has a
slight (very slight) advantage.

In Internet Explorer 6.0.2900 the first test has a significant advantage
(around 60% faster). I'm pretty sure it has something to do with this:
<url: http://blogs.msdn.com/ericlippert/archive/2003/11/6.aspx />

---

If "bar" is not an object then how is it possible to say

print("bar".toUpperCase());


? Well, actually, from the point of view of the specification, this is
just a syntactic sugar for



print((new String("bar")).toUpperCase());



Now, of course as an implementation detail we do not actually cons up a
new object every time you call a property on a value type! That would
be a performance nightmare. The runtime engine is smart enough to
realize that it has a value type and that it ought to pass it as the
"this" object to the appropriate method on String.prototype and
everything just kind of works out.



---

JScript doesn't actually "con up" a new String() everytime, the other
implementations either: a) do "con up" a new String() everytime; or b)
take longer figuring out that they don't have to.

Anyway, my question wasn't really about performance, but more about
proper design. Handle everything as a string, or as a String object, or
switch back and forth as necessary.
The only reason to use object wrappers Object(), Boolean(), Number()
and String() would be to create customized objects with extra
properties and methods.

Maybe I don't understand what you are saying, but I disagree with the
way I'm interpretting it. I don't need to wrap a string in a String
object to use custom methods/properties I've added to the String
prototype:

String.prototype.repeat = function(n) {
return (new Array(n + 1)).join(this);
}
alert("abc".repeat(5));

Maybe you meant:

function MyString(s) {
var value = String(s);
this.toString = function() {
return value;
}
}
MyString.prototype = new String();
var ms = new MyString("abc");
alert(ms);

But then I'm creating a MyString object, not a String object.
 
T

Thomas 'PointedEars' Lahn

Grant said:
No I'm not. My question was basically: Since the underlying
implementation, when confronted with "string".charAt(0); converts this
to new String("string").charAt(0); is it better to do this yourself in
advance as a matter of design (without regard for performance)?
No.


No it isn't.

Yes it is.
As I've shown, in most Web browsers it is more performant
(by a neligible margin) to wrap a string in a String object yourself
before calling a String.prototype method on it.

var s = 'test string';
var t = (new Date()).getTime();
for (var ii = 0; ii < 100000; ++ii) {
var x = s.charAt(0); // typeof 'string'
}
document.write(((new Date()).getTime() - t) + '<br>');
var t = (new Date()).getTime();
for (var ii = 0; ii < 100000; ++ii) {
var x = (new String(s)).charAt(0); // typeof 'object'
}
document.write(((new Date()).getTime() - t) + '<br>');

Loops: 100
Repeats: 10

Result:
--------

Expressions:

[1] "foo".charAt(0)
[2] new String("foo").charAt(0)

Evaluation Results (ms):

\n| 1 2 3 4 5 6 7 8 9 10 min max avg
e\|______________________________
1| 34 55 54 33 55 31 55 32 53 32 31 55 43.4
2| 57 57 35 59 56 36 89 37 57 55 35 89 53.8

User Agent:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050517
Firefox/1.0.4 (Debian package 1.0.4-2) Mnenhy/0.7.2.0

Although this is still a singular result, the second expression in the
average always took more time to be evaluated than the first one, in all
of the 10 tests of the 10 x 100 loops performed.
In Firefox 1.0.4, [...] (reduced loop counts from 100000 to 10000) the
second test (where I wrap the string in a String object before invoking
charAt() on it) has a slight (very slight) advantage.

I cannot second that.


PointedEars
 
M

Michael Winter

On 02/06/2005 18:31, Thomas 'PointedEars' Lahn wrote:

[snip]
[1] "foo".charAt(0)
[2] new String("foo").charAt(0)

[snip]

If you're merely evaluating one-time object instances, then the latter
will always be slower due to the overhead involved in the NewExpression.
I implied that much in my post. However, if the same object instance can
be used multiple times, then it will be quicker as there is no need to
create an intermediary. Evaluating new String(...) outside the inner
test loop should demonstrate this. I see an improvement of about 62%.

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,615
Members
45,299
Latest member
JewelDeLaC

Latest Threads

Top