It happens because your element does not have a parent. Append it to the DOM or to another jQuery collection and it will work.
I created a little demo that might help in understanding what this method does.
DETAILS:
I will sum up the research that is detailed in the comments below this answer. Thanks to PSL, calberts, Jason P and A. Wolff.
The documentation of replaceWith
states the following:
As of jQuery 1.4, .replaceWith() can also work on disconnected DOM
nodes. For example, with the following code, .replaceWith() returns a
jQuery set containing only a paragraph.:
$( "<div/>" ).replaceWith("<p></p>" );
This means that the example provided by the OP should indeed work. And it works till version 1.8. Unfortunately, from version 1.9 it stops working. This seemed to be a bug and only happens if you are trying to replace the "root element" of the jQuery object.
Actually the change in 1.9 was documented:
Prior to 1.9, .after(), .before(), and .replaceWith() would attempt to
add or change nodes in the current jQuery set if the first node in the
set was not connected to a document, and in those cases return a new
jQuery set rather than the original set. This created several
inconsistencies and outright bugs--the method might or might not
return a new result depending on its arguments! As of 1.9, these
methods always return the original unmodified set and attempting to
use .after(), .before(), or .replaceWith() on a node without a parent
has no effect--that is, neither the set or the nodes it contains are
changed.
Problem is that the change never made it to the official docs. I found a bug posted about this, but it was closed because it belongs to a different tracker.
Quick Solution:
In the OP's situation, the easiest way to "replace" the element would be
var obj = $('<div id="obj">Text</div>');
obj = $('<span>New text</span>');
but only if it is not in the DOM yet :).