-1

Simply why does String.prototype log the string object with the standard curly brackets and key value pairs, and the Array.prototype log the array object just like an array, with square brackets and values?

String.prototype.test = function(){
    console.log(this); // logs { '0': 't', '1': 'e', '2': 's', '3': 't' }
};
var str = 'test';
str.test();
Array.prototype.test1 = function(){
    console.log(this); // [1,2,3,4]
};
var arr = [1,2,3,4];
arr.test1();
  • 1
    `this` in a string method is a string object. Why would it surprise you that you can call string methods on a string object? `Array` does follow the same pattern - you can add methods to it and access `this` in those methods. Not sure what you're asking about `Array`. – jfriend00 Sep 27 '14 at 07:01
  • when you log 'this' within the siring prototype it is an object, as in it has keys and values. it surprises me because if you try to call string methods on any other type of object it will not work. My question is what makes a string object different and unique from a regular object? – user2770599 Sep 27 '14 at 07:06
  • Also, if you log 'this' in the Array prototype it will log an array and not an object.. not following the same pattern. – user2770599 Sep 27 '14 at 07:07
  • @user2770599—in ECMAScript ed 3, *this* **must** be an object. ES5 allows it to be any value, but the way you are calling the string methods, *this* will be the string converted to an object as if by `new String(string)`. Other primitives (like Number and Boolean) act the same way. Oh, an Array **is** an Object. – RobG Sep 27 '14 at 07:08
  • RobG - What do you mean by the why Im calling the methods? thx. – user2770599 Sep 27 '14 at 07:11
  • @user2770599—a function's *this* is set by how you call the function (or by using *bind*). When you call a String method like `testStr.test` then since *testStr* is a primitive with a dot accessor, it's converted to an object to resolve the property name. So *this* within *test* will effectively be the result of `new String(testStr)`, but noting that the value of *testStr* doesn't change, it's an Object for the sake of executing the expression only. – RobG Sep 27 '14 at 07:14
  • An array is an object, so is a function. How `console.log()` chooses to display a given type is purely based on how `console.log()` was written and not an indicator that means any more than that. Use `typeof` if you want to know what something actually is. – jfriend00 Sep 27 '14 at 07:16
  • So i get that everything in JS is an object, like functions, arrays, and also strings. But how does JS know that it is a string object verses an array object? What property on this object indicates if it is a string type and has the siring methods available to it? – user2770599 Sep 27 '14 at 07:18
  • Use `typeof str` or `typeof arr` to see what kind of object something is. It's built into the language to tell you what type of data something is. `Array` is an odd-ball and will report `typeof arr === "object"`. There are other ways to see if it's actually an array. – jfriend00 Sep 27 '14 at 07:19
  • @user2770599—javascript is loosely typed, all values have a [*Type*](http://ecma-international.org/ecma-262/5.1/#sec-8). Variables are just containers for values and don't have a type. An array inherits from Array.prototype, which inherits from Object.prototype, so array instances inherit from both. Note that `typeof []` returns 'object'. – RobG Sep 27 '14 at 07:21
  • @jfriend00 - yes like Array.isArray(arr) is a boolean – user2770599 Sep 27 '14 at 07:29
  • @user2770599 - String.prototype, like Array.prototype will both inherit from Object.prototype, so all strings have object methods and string methods, just like all arrays have array methods and object methods? – user2770599 Sep 27 '14 at 07:30
  • See this to understand how `this` works in javascript: http://stackoverflow.com/questions/13441307/how-does-the-this-keyword-in-javascript-act-within-an-object-literal/13441628#13441628 – slebetman Sep 27 '14 at 07:46
  • After you've read the link above, the answer is because `.test()` with the syntax `testStr.test()` and therefore the `this` within it is set to `testStr` which is a string. Not really surprising that you're able to call string methods on a string. – slebetman Sep 27 '14 at 07:48
  • dudes i think we got derailed from my question. to hone in on my question, simply why do I log key value pairs, with curly brackets in String.prototype, and I only log the array with square brackets when I call Array.prototype? String.prototype.test = function(){ console.log(this); // logs { '0': 't', '1': 'e', '2': 's', '3': 't' } }; var str = 'test'; str.test(); Array.prototype.test1 = function(){ console.log(this); // [1,2,3,4] }; var arr = [1,2,3,4]; arr.test1(); – user2770599 Sep 27 '14 at 08:18
  • That has to do with auto-promotion of native types to objects. You see, native types like strings and numbers are not objects. But they have their corresponding constructors. When you try to call a method on something that is not an object javascript will see if it can promote it to an object temporarily. I got stumped about this as well once. Be warned though, this behavior is not exactly standard since it's implementation detail. An interpreter may very well implement native types as proper objects. – slebetman Sep 27 '14 at 08:33
  • I'll write up an answer for this later. – slebetman Sep 27 '14 at 08:33
  • Can you add your comment: "why does my log look that way" in your question. I think we've all read it wrong and assumed you simply don't know how objects and this works in javascript. The specific question of why does the string not look like a string inside its own method is a good and valid question. – slebetman Sep 27 '14 at 08:35
  • @slebetman - Thank you! that answers my question, so much JS so much to learn :), good point I'll reformat my question – user2770599 Sep 27 '14 at 08:40

1 Answers1

3

Because in a method call the this argument is always (in sloppy mode) casted to an object. What you see is a String object, which was produced from the "test" primitive string value. The array on which you call your method is already an object, so nothing happens and you just get the array as before.

If you use strict mode, this cast doesn't happen:

String.prototype.test = function() {
    "use strict";
    console.log(this);
};
var str = 'test';
str.test(); // logs "test"
Bergi
  • 630,263
  • 148
  • 957
  • 1,375