When you use new, the value of this inside the constructor points to the newly created object (for more information on how new works, take a look at this answer and this answer). So your new instance i, has a hello function. When you try to access the property of an object, it walks up the prototype chain until it finds it. Since hello exists on the instance of the object, there is no need to walk up the prototype chain to access the version of hello that returns hhhhhhhh. In a sense, you have overridden the default implementation in your instance.
You can see this behavior if you don't assign hello to this inside your constructor:
var O = function(someValue) {
 }
 O.prototype.hello = function(){
       return "hhhhhhh";
 }
 var i = new O("chris");
 console.log(i.hello()); //this prints out hhhhhhh
What you're doing is kind of backwards. The prototype basically provides the "default" form of something, which you can override on a per-instance basis. The default form is used only if the property you're looking for cannot be found on the object. That is, JavaScript will start walking up the prototype chain to see if it can find a property that matches what you're looking for. It it finds it, it will use that. Otherwise, it will return undefined.
What you basically have in the first case is as follows:
Object.prototype.hello (not defined; returns "undefined")
|
+----O.prototype.hello (returns "hhhhhhhh")
     |
     +----i.hello (returns "hello, chris")
So when you do i.hello, JavaScript sees that there is a hello property on i and uses that. Now if you didn't explicitly define a hello property, you basically have the following:
Object.prototype.hello (not defined; returns "undefined")
|
+----O.prototype.hello (returns "hhhhhhhh")
     |
     +----i.hello (is "undefined", so JavaScript will walk up the chain until 
                   it sees O.prototype.hello, which does have a defined value 
                   it can use.)
What this means is that you can provide a default implementation in the prototype, and then override it (in a sense it's like sub-classing). What you can also do is modify the behavior on a per-instance basis by directly modifying the instance. The version of hello that you have on the prototype is kind of a fail-safe and a fall-back.
EDIT: Answers to your questions:
Overriding on a per-instance basis means you attach a property or a function to a particular instance. For example, you could do:
i.goodbye = function() {
    return "Goodbye, cruel world!";
};
Which means that this behavior is specific to that particular instance (i.e., only to i and not to any other instances that you may have created).
If you take out this, then you have basically have:
hello = function() {
    return "hello, " + someValue;
}
Which is equivalent to doing:
window.hello = function() {
    return "hello, " + someValue;
}
So in this case, hello is a global reference to that function. What this means is that hello isn't attached to any of your objects.
hello can be undefined if you don't have this.hello = function() { .... }; inside your constructor. I was also talking about the general process that JavaScript uses to try to resolve properties on objects. As I mentioned before, it involves walking up the prototype chain.