I understand the construction function is a special function returning a object. But
> Animal = function (){this.species='animal'}
> a=new Animal()
> b={species:'animal'}
> a==b
==> false
Why?
Comparisons like that are not "deep" comparisons. Either "a" and "b" refer to the exact same object or they don't.
To put it another way, by comparing the two variables you're comparing references to objects, not the objects themselves.
edit — there's a difference between primitive types (booleans, numbers, strings) and object references. Like I said, what you've got in your question is a pair of object references. Two object references are considered equal if they refer to the same object. In your case, they don't. They're two different objects that happen to have the same property with the same value. The properties of the objects do not play a part in the == comparison because that's simply how the language is defined to work.
Related
I have this code:
var object1 = {same:'test'}
var object2 = {same:'test'};
console.log(object1 === object2)
It returns false in the console.
I also have this code:
var object1 = {same:'test'}
var object2 = object1;
console.log(object1 === object2)
It returns true in the console.
I know '===' is an equality operator, but I don't know how it works on objects.
Why does the first example return false?
See this ball? Its colour is red. Call it ball1.
See this ball? Its colour is red. Call it ball2.
Is ball1 the same object as ball2? No, they are distinct objects that happen to have identical properties.
See this ball? Its colour is red. Call it ball1.
Let's call ball1, ball2.
Is ball1 the same object as ball2? Yes. They are the same ball.
Objects are compared by reference equality, and since object1 and object2 are two distinct instances, they are different objects (think of it as: they occupy different places in memory).
If however you assign object1 to object2, they both point to the same place in memory and thus are equal (they are two references to the same single object, it only exists once in memory). Changing a property through object1.same = 'uiae'; will update the property object2.same as well (because they are in fact the same identical object and the same property)
var object1 ={same:'test'}
var object2 ={same:'test'};
console.log(object1 === object2)
In this case you are creating two different objects. that's why it returns false value in console when checking with === operator.
var object1 ={same:'test'}
var object2 =object1;
console.log(object1 === object2)
In this case you are creating one object and object1 & object2 referencing to created object, that's why it returns true when you are checking with === operator.
In second case if we change the object2["same"]="test2" then object1["same"] value also be changes to test2.
In first case it won't happens like that, because object1 & object2 are two different objects.
refer this:
Object Equality in JavaScript
hopes this is may be helpful.
In the first case Object1 and Object2 are two different reference points(or variables) pointing at two different objects in memory.so when you check them for equality the result is false.
In the second case you are just copying the reference point(address) from Object1 to Object2 meaning both the reference points are now referring the same object in memory.so the result true.
Objects are always compared by reference.
When you assign objects or arrays from one variable to another, it copies a reference to the original object, so the two objects are equal.
Each time you write an object or array literal, it makes a different object or array, so they're not equal, even if the contents are similar.
When you have created object this way, you have created a map.
There is nothing like value of a map as its not of primitive types.
So equals would just check for the reference equality. Hence this fails.
In the second case, the reference equality goes through.
Two different object can't be equal to each other by definition in JavaScript. Equal attributes and values are not important. They have different pointers (first example).
In the second example, you are cloning the object with the reference. So "===" will return true.
In your first example you created two distinct objects with arbitrary content, which is randomly the same: {same:'test'} and {same:'test'}
In your second example you created only one object, and stored it in two variables: object1 and object2
The === checks for object identity, that means the objects in the compared variables must be the same.
Your example does not relate to the == vs === operator difference. As people explained before, your example simply creates two different object and in the next example reference the same. Both == and === would act the same there.
Since objects litterals are always objects litterals and not in any way implicitly convertible, == and === will always act the same for objects litterals. Some other types like NaN, null and the like, you get weird/funny results when comparing with == and ===
This is how javascript handling and comparing objects:
As I've tested, $('foo') is an instance of jQuery, and not an instance of Array. And AFAIK, javascript doesn't have operator overloading.
So how can $('foo')[0] return the corresponding HTMLElement if $('foo') is not an instance of Array?
I tried to look at jQuery's source code but it's a bit too much for me right now.
Thanks for any insight.
Because you can use brackets notation with any object in JavaScript, not just arrays. In fact, normal arrays aren't really arrays at all in JavaScript, they're just objects with a specific prototype and special treatment of a class of property names ("array indexes") and a special length property.
Brackets notation can be used to access any object property1 via its string name (and believe it or not, [0] is converted to ["0"] when accessing arrays, in theory).
Example:
var obj = {foo: "bar", 0: "zero"};
console.log(obj[0]); // zero
console.log(obj["0"]); // zero
console.log(obj.foo); // bar
console.log(obj["foo"]); // bar
var f = "f" + "o" + "o";
console.log(obj[f]); // bar
The object above has two properties of its own. Their names are "0" and "foo"; both names are strings (even though I wrote 0 as a numeric literal in the initializer; it gets coerced to string).
jQuery maintains its "array entry" properties to ensure that you can use brackets notation to access them. It also maintains a length property.
If jQuery were being written from scratch today, it probably would extend Array. But when jQuery was written, you couldn't extend Array. (It only became possible as of ES2015's ("ES6's") class feature.)
1 Except properties that don't have a string name; ES2015 introduced the concept of properties with names that are Symbols rather than strings. Prior to that, all object property names were strings (even array indexes).
I have the following code:
String.prototype.isLengthGreaterThan = function(limit){
return this.length > limit;
}
console.log("John".isLengthGreaterThan(3));
Number.prototype.isPositive = function(){
return this > 0;
}
console.log(5.isPositive(3)); //error
The 1st example work, the other doesn't. Why?
From my understanding, primitives are not objects – though they do have access to their function constructor's prototype (Number, String, etc.). So, you can add methods directly to the prototype. In my example above it didn't work in one instance.
I am looking for "under the hood" answer, to understand what happens when you do, for example:
var a = 1;
How does it really have an access to its prototype if it isn't an object?
The dot thing isn't to do with primitives, it's just the syntax of writing numeric literals. In a number, the . is a decimal point, whereas of course that's not the case for a string. To use a method on a literal number, you have two choices:
Parens:
console.log((5).isPositive(3));
Two dots (yes, really):
console.log(5..isPositive(3));
In the second case, it works because the first dot is a decimal point; this means that the dot following can't be a decimal point, and so it's the property accessor operator.
How does it really have an access to it's prototype if it isn't an object.
It's promoted to an object automatically by the JavaScript engine when you do the propety access. In the case of numbers, it's as though you called new Number(5) or similar. In the case of strings, it's as though you called new String("the string"). When the property access is complete, the temporary object is then discarded immediately when the expression is complete. Naturally, the JavaScript engine can optimize the object allocation out, but conceptually that's what happens.
So conceptually:
We do (say) var n = 1; The variable a contains the primitive number value 1.
We do n.isPositive(3); to create a string from it using Number.prototype.toFixed. That's a property access operation:
The engine evaluates the left-hand side, n, and gets the result 1 (a primitive number); this is the base it'll use for the property access operation.
The engine evaluates the right-hand side (isPositive) to determine the property key (name) to look up. In this case it's a literal, so the key is the string "isPositive". This is the property key for the property access operation.
The engine goes to look up the property on the base. Since the base we have is a primitive, the JavaScript engine promotes it (coerces it) to an equivalent Number object.
Since that object doesn't have a "isPositive" property, the engine looks at its prototype, Number.prototype, and finds it; it's a reference to a function.
Various things happen that aren't really germane, and ultimately isPositive is called with this being an object coerced from the primitive value 1. It does its work and generates its return value.
Since the temporary object isn't referenced by anything anymore, it's eligible for garbage collection.
The mechanism by which this happens is a bit scattered in the specification:
The runtime semantics of the property accessor operator return something called a Reference specification type, which basically is a purely abstract specification holding object that will get evaluated later. It says that the base will be the result of evaluating the left-hand side of the property accessor, and the property anme will be the result of evaluting the right-hand side.
The GetValue operation on the Reference type, which says (step 5) that if it's a property reference and the base is primitive, it's coerced via the specification's ToObject operation.
ToObject, which defines the rules for doing that.
in firebug console :
>>> a=12
12
>>> a.__proto__
Number {}
>>> (12).__proto__
Number {}
>>> a.constructor.prototype === (12).__proto__
true
>>> a.constructor.prototype.isPrototypeOf(a)
false
the final line causes me a great confusion as compared to the other lines. also see Constructor.prototype not in the prototype chain?
When you use the . operator with a primitive, the language auto-boxes it with the appropriate Object type (in this case, Number). That's because simple primitive types in JavaScript really are not Object instances.
Thus, the actual left-hand side of
a.__proto__
is not the number 12 but essentially new Number(12). However, the variable "a" continues to be the simple number value 12.
edit — Section 8.7 of the spec "explains" this with typical ECMA 262 moon language. I can't find a clear paragraph that describes the way that a primitive baseValue is treated as a Number, Boolean, or String instance, but that section directly implies it. I think that because those non-primitive synthetic values are ephemeral (they're only "real" while the . or [] expression is being evaluated) that the spec just talks about the behavior without explicitly requiring that an actual Number is constructed. I'm guessing on that however.
#Pointy has explained it very well. Basically, if you want your last statement to be true, you would have to write it like:
a.constructor.prototype.isPrototypeOf(new Number(a));
In JavaScript primitives do not have a prototype chain. Only objects do. A primitive value includes:
Booleans
Numbers
Strings
Null
Undefined
Hence if you call isPrototypeOf with a primitive value then it'll always return false.
If you try to use a boolean, number or string as an object then JavaScript automatically coerces it into an object for you. Hence a.constructor evaluates to new Number(a).constructor behind the scenes. This is the reason you can use a primitive value as an object.
If you wish to use a variable storing a primitive value as an object often then it's better to explicitly make it an object. For example in your case it would have been better to define a as new Number(12). The advantages are:
JavaScript doesn't need to coerce the primitive to an object every time you try to use it as an object. You only create the object once. Hence it's performance efficient.
The isPrototypeOf method in your case will return true as a will be an instance of Number. Hence it will have Number.prototype in its prototype chain.
Crockford writes in http://javascript.crockford.com/survey.html:
"There are two ways to make a new array:
var myArray = [];
var myArray = new Array();"
So I'm confused by these two lines in some AJAX code I am reading:
var obj={}; // obj is an Object object (i.e. a hash table)
obj[4] = 'x'; // now obj is suddenly an Array object via an integer key?
In JavaScript are an object and an array really just the same thing, but with a variant on the key type?
In other words, is this the same as in php where we can use either a name (string) or an integer for a hash key?
I've Googled for an answer on this but can't seem to nail down an article which discusses this issue.
One possibility that comes to mind is that perhaps the first line is syntactic lint because the 2nd line overwrites the previous definition of obj as it creates a new Array object.
it does not become an array, it is simply an Object with a '4' property, like this:
var obj = {
'4': 'x'
};
it is just converted to a string when used as a property like obj['4'] = 'x';
Everything but primitive datatypes is an object in JavaScript. Objects can have a properties and there are two ways to access object properties:
Dot notation, foo.bar, which you can use as long as the property name is a valid identifier.
Bracket notation, foo['bar'] which you have to use if the key is not a valid identifier [spec]. For example, if it is a number, or contains a space or you have a variable with the name.
Hence, bracket notation is not a characteristic of arrays and if you see it, it does not mean the value is an array. It is simple one of two ways of accessing properties.
The elements of an array are just properties with numeric keys. Arrays are built on top of objects and implement some additional methods which treat these numeric properties in a special way. For example the .length property is automatically updated when you add new elements. But ultimately they are just normal properties.
In your example you have a simple object. You have to access the property with obj[4] or obj['4'] because obj.4 is invalid since 4 is not a valid identifier (basically everything that you can use as variable name is a valid identifier. var 4 = 'foo'; is invalid).
And since arrays are just objects, if you could use numbers as identifiers, you were also able to access an element with arr.4.
As far as I know, no, an object can't be coerced into an array. But, it can look and act like an array, and that's what's happening here. Numbers, and anything else that can be coerced to a string, are perfectly valid property names for Javascript objects, so
obj[4] = 1;
obj['spam'] = 2;
are both valid ways of setting a property on the object. That doesn't make the object an array. An Array is a special class of object with specific methods (.slice(), .concat(), etc) and a length property that's kept up to date with the number of items in the array.
Yes
Javascript Array is very different from tradition array, you can think of it as object.
var array = [1,2,3] is equivalent to var object = {'0' : 1, '1' : 2, '2' : 3}
except array inherited from Array.prototype and object inherited from Object.prototype, where Array.prototype will contain method such as length.
Javascript is a loosely-typed, prototype-based language. Even primitive types like a boolean can be treated like an object (though you aren't going to get far). Almost everything in javascript is, at root, an object.
Understanding this, an array IS an object. You can arbitrarily add properties to any object:
var xml = new XMLHttpRequest();
xml[4] = 'x';
console.log(xml);
That object is still an instance of XMLHttpRequest. It now has a property labeled 4 with a value of x. You can treat anything like this -- even a function:
var test_func = function () {
alert('woah!');
}
test_func[4] = 'x';
console.log(test_func[4]);
The take-away here is that the obj[key] = value notation is NOT indicative of an "array" type, like it is in languages such as PHP. Rather, it is an alternate way to access properties of any object, and is equivalent to obj.key = value (you can't use obj.4 = 'x', though, that's invalid syntax). The other take-away is that any object in javascript can be modified or used in pretty much any way. You shouldn't misuse objects, but you can
Check it out here: http://jsfiddle.net/w2AqJ/
Documentation
Array on MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
Javascript "associative arrays" considered harmful by Andrew Dupont - http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/