var obj = [ "one", "two", "three"];
$.each(obj, function() {
console.log(this);
});
The output I get is
{ '0': 'o', '1': 'n', '2': 'e' }
{ '0': 't', '1': 'w', '2': 'o' }
{ '0': 't', '1': 'h', '2': 'r', '3': 'e', '4': 'e' }
I suppose to get "one" "two" "three", but I get the following weird results, anyone can explain?
var obj = [ "one", "two", "three"];
$.each(obj, function() {
console.log(this);
});
The output I get is
{ '0': 'o', '1': 'n', '2': 'e' }
{ '0': 't', '1': 'w', '2': 'o' }
{ '0': 't', '1': 'h', '2': 'r', '3': 'e', '4': 'e' }
I suppose to get "one" "two" "three", but I get the following weird results, anyone can explain?
Share Improve this question edited Aug 17, 2012 at 14:38 James Williams 4,2161 gold badge21 silver badges35 bronze badges asked Aug 17, 2012 at 14:37 Adam LeeAdam Lee 25.8k52 gold badges165 silver badges245 bronze badges 3- 1 because that's what the object really looks like, like all javascript objects. Keys and associated values. If you just want to log the values, do that :) – Phillip Schmidt Commented Aug 17, 2012 at 14:40
- Related: stackoverflow./questions/9039121/… – gen_Eric Commented Aug 17, 2012 at 14:42
- @PhillipSchmidt: That's not quite what's he's asking. He's why it's an object (and not a string). – gen_Eric Commented Aug 17, 2012 at 14:46
6 Answers
Reset to default 5this
is always an object there. A string object consists of key/value pairs where keys are indices and values are characters at that index in the string. Try Object("foo")
to create such an object yourself.
By using strict mode you can suppress that:
$.each(obj, function() {
"use strict";
console.log(this);
});
In javascript (not just jQuery), this
is a special keyword referring to an object bound to the current scope (unless it has been changed). Within the $.each
function, the scope context of the loop function (the function you pass) is bound to the item that you're looping. That may be the case, but it isn't reliable nor is it very useful or interesting.
Observe:
var clams = { 'tomato!':'gross' };
var items = ["one", "two", "three"];
$.each(items, function (index, item) {
console.log('this',this);
console.log('item', item);
}.bind(clams));
Try it: http://jsfiddle/LBfet/
While it is possible to use this
within an $.each
loop, I would suggest using it the way the documentation provides, which is that your looping function support the signature callback(indexInArray, valueOfElement)
.
Documentation: http://api.jquery./jQuery.each/
Consider it a quirk.
More Reading
- The this keyword* on quirksmode - http://www.quirksmode/js/this.html
jQuery.each
- http://api.jquery./jQuery.each/
What's happening here is that jQuery is using .call
to set the value of this
inside the callback to $.each
.
When .call
is called, the value of this
is converted to an object (as per the JavaScript spec: http://es5.github./#x10.4.3).
This is also noted in the jQuery docs: http://api.jquery./jQuery.each/
The value can also be accessed through the
this
keyword, but Javascript will always wrap thethis
value as an Object even if it is a simple string or number value.
"Strict mode" (which only works in modern web browsers, so not IE: http://caniuse./#feat=use-strict) actually changes this behavior and allows this
to be a primitive (this is documented in the spec: http://es5.github./#x15.3.4.4):
$.each(obj, function() {
"use strict";
console.log(this);
});
You can also use .valueOf()
to convert the object back into its respective primitive:
$.each(obj, function() {
console.log(this.valueOf());
});
A javascript string, down to the basics, is an object. This object is broken down into an array of characters. This is why you can call some of the same functions on a string object like an array.
Any time you manipulate a string literal, in this case, it is changed to a string object. A string object is an array of characters. This would allow for easily capitalization when using functions like: toUpperCase() & toLowerCase() - (along with others)
Using this
, as others have stated, is referenced as an object. Here is a little test code to show how a string is like an array:
var testStr = "test";
var obj = [ "one", "two", "three"];
console.log(testStr.charAt[1]); // Will return 'e'
console.log(testStr[1]); // Will return 'e'
console.log(obj[1]); // Will return 'two'
console.log(testStr.length) // Will return 4
console.log(obj.length) // Will return 3
A string literal in the case of var testStr = "string"
is a primitive data type with no functions. But a String Object is used to manipulate the data with functions and non-primitive data types.
Now I am going to create a string object and output it to console: (This is what happens when you manipulate a string literal, it gets converted to a string object)
strTest = new String("TEST String");
console.log(strTest);
You will get:
String
0: "T"
1: "E"
2: "S"
3: "T"
4: " "
5: "S"
6: "t"
7: "r"
8: "i"
9: "n"
10: "g"
length: 11
__proto__: String
anchor: function anchor() { [native code] }
big: function big() { [native code] }
blink: function blink() { [native code] }
bold: function bold() { [native code] }
camelCase: function (){return this.replace(/-\D/g,function(match){return match.charAt(1).toUpperCase();});}
capitalize: function (){return this.replace(/\b[a-z]/g,function(match){return match.toUpperCase();});}
charAt: function charAt() { [native code] }
charCodeAt: function charCodeAt() { [native code] }
checkAllAvailableTags: function (){var b=this,d;for(d in c)c.hasOwnProperty(d)&&(b=b.replace(d,c[d]));return b}
clean: function (){return this.replace(/\s{2,}/g,' ').trim();}
concat: function concat() { [native code] }
constructor: function String() { [native code] }
contains: function (string,s){return(s)?(s+this+s).indexOf(s+string+s)>-1:this.indexOf(string)>-1;}
escapeRegExp: function (){return this.replace(/([.*+?^${}()|[\]\/\\])/g,'\\$1');}
fixed: function fixed() { [native code] }
fontcolor: function fontcolor() { [native code] }
fontsize: function fontsize() { [native code] }
hexToRgb: function (array){var hex=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(hex)?hex.slice(1).hexToRgb(array):false;}
hyphenate: function (){return this.replace(/\w[A-Z]/g,function(match){return(match.charAt(0)+'-'+match.charAt(1).toLowerCase());});}
indexOf: function indexOf() { [native code] }
italics: function italics() { [native code] }
lastIndexOf: function lastIndexOf() { [native code] }
length: 0
link: function link() { [native code] }
localeCompare: function localeCompare() { [native code] }
match: function match() { [native code] }
replace: function replace() { [native code] }
rgbToHex: function (array){var rgb=this.match(/\d{1,3}/g);return(rgb)?rgb.rgbToHex(array):false;}
search: function search() { [native code] }
slice: function slice() { [native code] }
small: function small() { [native code] }
split: function split() { [native code] }
strike: function strike() { [native code] }
sub: function sub() { [native code] }
substr: function substr() { [native code] }
substring: function substring() { [native code] }
sup: function sup() { [native code] }
test: function (regex,params){return(($type(regex)=='string')?new RegExp(regex,params):regex).test(this);}
toFloat: function (){return parseFloat(this);}
toInt: function (){return parseInt(this,10);}
toLocaleLowerCase: function toLocaleLowerCase() { [native code] }
toLocaleUpperCase: function toLocaleUpperCase() { [native code] }
toLowerCase: function toLowerCase() { [native code] }
toString: function toString() { [native code] }
toUpperCase: function toUpperCase() { [native code] }
trim: function trim() { [native code] }
trimLeft: function trimLeft() { [native code] }
trimRight: function trimRight() { [native code] }
valueOf: function valueOf() { [native code] }
__proto__: Object
As this is an object you can simply use the toString method to output its contents.
$.each( obj, function() {
console.log( this.toString() );
});
Why the output is what it is: As pimvdb says: this is a pointer to an object. jQuery applies the anonymous function as a callback to each value. If that value isn't an object, jQ will make it into one. Hence, three objects are logged.
Couple to that that strings are, for puters, one of the hardest things to cope with! It's just a series (array) of chars. That's why, in C, and many other languages the string type doesn't (didn't) exists. A string is an array, and since Arrays are augmented objects in JavaScript (first version didn't even have them), you get the output you get.
It's not that big of a problem, though:
obj = [ "one", "two", "three"];
$.each(obj, function()
{
console.log(this+'');
});
Solves this (somewhat). But add typeof this
and you'll see it still is an object, add this instanceof String
, and you'll get true. To get rid of those pesky string objects (they are pesky), and get clean string constants:
obj = [ "one", "two", "three"];
$.each(obj, function(i,el) {
console.log(el);
});
That's it: instead of applying the function as a method, jQ will now pass the key and value pair as arguments, where i is the key and v is the value.