Best object questions in April 2012

What kind of object shows up in the console as [object Text]?

9 votes

Say I have the following element:

<p id="thingy">Here is some <em>emphasized</em> text!</p>

In a Javascript console, I'll get its contents with jQuery:

> var theContents = $('<p id="thingy">Here is some <em>emphasized</em> text!</p>').contents();

theContents is now an array that looks like this:

> theContents
["Here is some ", <em>​emphasized​</em>​, " text!"]

So far so good; it seems to be an array, where elements 0 and 2 are strings, and element 1 is a jQuery object. If I output just the first element, it seems to confirm my guess:

> theContents[0]
"Here is some "

However, if I try to concatenate it with another string, I see that I am lacking some understanding:

> 'Hello! ' + contents[0];
"Hello! [object Text]"

So that variable looks like a string, but it is in fact some kind of object. For that matter, the jQuery object in the middle doesn't show up as a regular object, either; it shows up as the raw markup.

Another question references the same problem, but doesn't actually explain it. I've found that I can use contents[0].textContent to solve my real problem, but that still doesn't help me understand exactly what is going on here. Can someone explain to me in detail why all this is behaving the way it is?

Most jQuery functions return a jQuery object, which for convenience looks and works like an array for most purposes. To quote the documentation, "A jQuery object contains a collection of Document Object Model (DOM) elements" (or "nodes"). So you can assume that each member of the collection is a DOM node, not a string, and accordingly the object you're looking at is a Text node.

In JavaScript when you do string concatenation each operand that isn't a string is automatically converted to one by calling its toString() method. So, just as "1,2,3" is the string representation of the array [1, 2, 3] and "[object HTMLDivElement]" represents a node created with the HTML "<div>", "[object Text]" represents a Text node.

You can read the specification here. Since interface Text inherits from CharacterData it has a data property that contains the string itself. And so:

var theContents = $( '<p id="thingy">Here is some <em>emphasized</em> text!</p>' )
                    .contents();

console.log( theContents[0].data );
// => "Here is some "

console.log( "Hello! " + theContents[0].data );
// => "Hello! Here is some "

Saving javascript objects using jquery and passing an ID from database

5 votes

I am using jQuery to save the values of my javascript objects. I need to retreive the ID of inserted object from the database. I know how to do it, if the Save function is within the javascript object (see code below). But how can I set the ID variable, if the Save function is not in the javascript object?

Working:

Person = function() {
    var self = this;

    self.ID;
    self.Name;
    self.SurName;

    self.Save = function() {
        $.ajax({
            type: "POST",
            url: "Save",
            contentType: "application/json; charset=utf-8", 
            data: JSON.stringify({ Name: self.Name, SurnName: self.SurName }),
            dataType: "json",
            success: function (result) {
                var ID = result.d.ID; //this is the ID retreived from database
                self.ID = ID; //set the ID, it works, since I can reference to self
            }
        });
    };
}¨

So how would I now implement a function (outside the Person class!) like:

SavePerson = function(p) {
     $.ajax({
        type: "POST",
        url: "Save",
        contentType: "application/json; charset=utf-8", 
        data: JSON.stringify({ Name: p.Name, SurnName: p.SurName }),
        dataType: "json",
        success: function (result) {
            var ID = result.d.ID; //this is the ID retreived from database
            p.ID = ID; //set the ID, it doesn't work, becouse if I call SavePerson repetedly for different objects, a p will not be a correct person.
        }
    });
};

Just to clarify, you would like the Person object id property to be updated with the recent save? If so the following script would suffice. I have used deferred's to ensure that p.ID is only updated upon completion of the asynchronous request.

$.Person = function() {
    var self = this;
    self.ID;
    self.Name;
    self.SurName;
}

$.SavePerson = function() {
var dfd = $.Deferred();
     $.ajax({
        type: "POST",
        url: "Save",
        contentType: "application/json; charset=utf-8", 
        data: JSON.stringify({ Name: p.Name, SurnName: p.SurName }),
        dataType: "json",
        success: dfd.resolve
    });
return dfd.promise();
};

var p = new $.Person();

$.SavePerson().then(function(result){
    p.ID = result.d.ID;
});