Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I add properties to a string object in javascript?

Tags:

javascript

I inherited some javascript code another developer wrote. He didn't like the grid component we used throughout the project, so he decided to write his own. The grid he wrote can't sort dates, because it can only bind to strings / numbers. He converts all dates to strings before using them. I looked at the string formatting of date function he wrote, and figured I could just add a date property to the string with the original value, and then when sorting see if the string has a date property and sort based on that. However, it seems like you can't add properties to strings in javascript. I wasn't aware there were certain types you can't add properties to. For example:

<html> <script> var test = "test"; test.test = "test inner"; console.log(test); console.log(test.test); </script> 

test.test will be undefined. Weird. My question is why this code doesn't work? And also, if you can think of any workarounds for sorting dates on that grid (besides actually binding to date objects instead of strings, which would be a pain to fix,) that would be really helpful.

like image 785
Shawn Avatar asked Mar 05 '11 02:03

Shawn


People also ask

Can you modify properties on an object?

Using the same method, an object's property can be modified by assigning a new value to an existing property. At this point, if we call the object, we will see all of our additions and modifications. Through assignment operation, we can modify the properties and methods of a JavaScript object.

Can we add properties to function in JavaScript?

Read this article: packtpub.com/article/using-prototype-property-in-javascript You cannot add a property x to a function fn like so: fn. x = 'something'. You need to use prototype.

How do you set a property for an object?

After you have created an object, you can set or change its properties by calling the property directly with the dot operator (if the object inherits from IDL_Object) or by calling the object's SetProperty method.


2 Answers

There are 8 language types in JavaScript:

  • 7 primitive types: Undefined, Null, Boolean, Number, BigInt, String, and Symbol
  • 1 non-primitive type: Object

Values of the primitive types are called primitive values and they cannot have properties.
Values of the Object non-primitive type are called objects an they can have properties.

When you try to assign a property named 'bar' to a variable foo, like so:

foo.bar = 'abc'; 

then the result will depend on the type of the value of foo:

(a) if the value of foo is of the type Undefined or Null, then an error will be thrown,

(b) if the value of foo is of the type Object, then a named property 'bar' will be defined on the object foo (if necessary), and its value will be set to 'abc',

(c) if the value of foo is of any other type, then a TypeError will be thrown in strict mode: “can't assign to property "bar" on foo: not an object”. In loose mode, the above assignment operation will be a no op. In either case, the variable foo will not be changed in any way.

So, as you can see, assigning properties to variables only makes sense if those variables are objects. If that is not the case, then the assignment will either do nothing at all, or even throw an error.


In your case, the variable test contains a value of the type String, so this:

test.test = "test inner"; 

does nothing at all.


However, since ES5 introduced accessor properties, there is an exception to what I've said above. Accessor properties allow us to define functions which are invoked whenever the property is either retrieved or set.

For instance:

var str = ''; str.prop; 

Here str is a variable holding a String value. Therefore, accessing a property of that variable should be a no-op (str.prop merely returns undefined). This is true with one exception: if String.prototype contains a accessor property 'prop' with a defined getter, then that getter will be invoked.

So, if this is defined:

Object.defineProperty( String.prototype, 'prop', {     get: function () {         // this function is the getter     } });  

then this

str.prop; 

will invoke that getter function. This also works in strict mode.

Live demo: http://jsfiddle.net/fmNgu/

However, I don't think that adding accessor properties to the built-in prototypes would be a good practice.

like image 131
Šime Vidas Avatar answered Sep 23 '22 18:09

Šime Vidas


If you use a String object you can add properties:

var test = new String("test"); test.test = "test inner"; console.log(test.toString()); // prints out "test" console.log(test.test); // prints out "test inner" 
like image 32
treaint Avatar answered Sep 22 '22 18:09

treaint