This question already has answers here:
new Number() vs Number()
(5 answers)
Closed 9 years ago.
I'm trying to understand the difference between writing m = Number() (which causes typeof m to evaluate as "number") vs m = new Number() (which causes typeof m to evaluate as "object").
I would have expected it to be an object either way. I was just messing around, and I added a .helloWorld() method to the Number prototype, and I was able to access it on m regardless of which method I used to instantiate it.
What's the difference here? What am I doing differently between writing Number() and new Number()? Why is one an object while the other is a number?
Number() by itself returns a number primitive. When you call new Number() you receive a new instance of an Object which represents Number's (relevant ES5 spec).
When you call a property on a primitive, the primitive is auto-boxed (like in Java) to an instance of that object, which is what lets you call helloWorld() on either the object or number.
However, try this;
var x = Number(5);
x.bar = function (x) { alert(x); };
x.bar("hello");
var y = new Number(5);
y.bar = function (x) { alert(x); };
y.bar("hello");
You'll see the latter works whilst the former does not; in the first, the number is autoboxed to a number, and the bar method is added to it (the object). When you call x.bar() you're creating a new auto-boxed Number, which bar doesn't exist on.
In the latter, you're adding a bar method to that Number instance, which behaves like any other Object instance, and therefore it persists throughout the lifetime of the object.
This is just how it is implemented. This particular constructor function, when called without new, returns a primitive number. When called with new, it returns the object-wrapped number.
You can access prototype methods/properties on primitives because behind the scenes, JavaScript converts them to objects, calls the prototype method, and then throws away the object copy. This allows you to do things like:
var myString = "foo";
console.log( myString.length ); //=> 3
console.log( typeof myString ); //=> "string"
An object copy of the primitive gets made on line two, the length property of the object is checked, and then the object copy is thrown away. myString stays as a string primitive.
Related
This question already has answers here:
Why, in JavaScript, does '3 instanceof Number' == false, but '3..method()' will call Number.prototype.method?
(1 answer)
javascript: do primitive strings have methods?
(2 answers)
Why does a primitive variable act like an Object? [duplicate]
(3 answers)
How does JavaScript .prototype work?
(26 answers)
Closed 2 years ago.
There was zero explanation about this in the book I'm reading. They just threw an example with this, and didn't bother to explain anything at all.
I keep testing and experimenting with this in an attempt to infer what it is and how it works exactly, and most of all, how is this different from just creating a new variable and then assigning a function to it.
Is the only difference just the fact that, you can use 'this' keyword with the String.prototype, because the String variable to which it has to be attached to becomes the parent object?
What I don't get it, what exactly are you creating? Are you creating a new method? Property? value? Just a function that can contain a value or some statement to be executed, and then you assign that function to .. a new String? Why do I need to assign the new function to a String in order to run it? If I just target the name of the function, it won't work. It has to attached to a String variable to execute the function. Why?
String.prototype.more = function() {
var confirm2 = 2 + 2;
return confirm2;
}
alert(more());
I can't create a new function and then try to run it without either writing the whole name "String.prototype.more()", or first creating a new variable, and then attaching the name "more" to it, and then the function is triggered.
Can somebody explain to me does String.prototype.something = function() {} create a new function and assign it to the 'something', and it could just contain a retuned value or a statement waiting to get executed? If so, how is this different from just creating a new variable and doing the same thing? Is the only difference the fact that you can use 'this' keyword? Why do I need to attach the function name to a String in order to run it? Am I not understanding something important here?
you can Use the prototype property to add a new property to all objects of a given type ,
in your example you are trying to add new property to the string type :
String.prototype.more = function() {
var confirm2 = 2 + 2;
return confirm2;
}
alert('example'.more());
//that will allert 4
JavaScript is a little weird in some aspects compared to other programming language.
JavaScript functions are full objects. In other languages functions are language constructs. For example if you create a function like this
function example1() {}
what you are really doing is creating an object of type function to the root object (which is the window object in your browser)
function example1() {}
console.log(window.example1) // function example1() {}
console.log(typeof window.example1) // function
Every object template in JavaScript has a prototype. So when you want to check for a function or a value of an object (hence called property), and that object doesn't have that property, JavaScript examines the prototype of that object, if the property is there. If that is not the case, JS will climb up the prototype ladder until it finds that property or reaches the end of the ladder (which is the object template)
In your case: String is the template object, if you create a string
// A is created as a new String
A = "a"
// The constructor of string is the String object which is a native function
console.log(String) // function String() { [native code] }
console.log(typeof String) // function
console.log(A.constructor === String) // true
// The String function has a prototype which contains all the functions of the String "class"
console.log(String.prototype) // function
// The method `sub` of the A object is in fact the method `sub` of the `String.prototype`
// that means A doesn't have the method sub for itself, but uses the
console.log(A.sub === String.prototype.sub) // true
// There are some other wild things going on that include `__proto__` and `constructor` properties.
console.log(String.prototype.__proto__.constructor === Object) // true
Regarding your case
String.prototype.more = function() {
var confirm2 = 2 + 2;
return confirm2;
}
a = "" // `a` is created as string has now a __proto__ property that points to String.prototype
// Following three are all the same
console.log(a.more) // more doesn't exist, but the more method of the prototype is used
console.log(a.__proto__.more) // `a.__proto__` is a reference to `String.prototype`
console.log(String.prototype.more)
Edit 1
Some more general examples
console.clear()
a = new Object()
// a now has automatically been assigned a `constructor` property, which is the `Object` function
console.log(a.constructor) // function Object()
// the Object function has a `prototype` property, which is an object
console.log(typeof Object.prototype) // object
// a is assigned a `__proto__` property, which is a reference to the `prototype` property of its `constructor`
console.log(a.__proto__ === a.constructor.prototype) // true
// a has inherited a method `hasOwnProperty` which tells us, if a property is directly on the object or is inherited from the prototype chain
console.log(a.hasOwnProperty('myNewProperty')) // false
a.myNewProperty = 'this is my own'
console.log(a.hasOwnProperty('myNewProperty')) // true
// Here you can see: `a` doesn't have the property `hasOwnProperty`, but the `__proto__` (which is `Object.prototype`) has
console.log(a.hasOwnProperty('hasWonProperty')) // false
console.log(a.__proto__.hasOwnProperty('hasOwnProperty')) // true
So I was playing around the other day just to see exactly how mass assignment works in JavaScript.
First I tried this example in the console:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
The result was "bar" being displayed in an alert. That is fair enough, a and b are really just aliases to the same object. Then I thought, how could I make this example simpler.
a = b = 'foo';
a = 'bar';
console.log(b);
That is pretty much the same thing, isn't it? Well this time, it returns foo not bar as I would expect from the behaviour of the first example.
Why does this happen?
N.B. This example could be simplified even more with the following code:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(I suspect that JavaScript treats primitives such as strings and integers differently to hashes. Hashes return a pointer while "core" primitives return a copy of themselves)
In the first example, you are setting a property of an existing object. In the second example, you are assigning a brand new object.
a = b = {};
a and b are now pointers to the same object. So when you do:
a.foo = 'bar';
It sets b.foo as well since a and b point to the same object.
However!
If you do this instead:
a = 'bar';
you are saying that a points to a different object now. This has no effect on what a pointed to before.
In JavaScript, assigning a variable and assigning a property are 2 different operations. It's best to think of variables as pointers to objects, and when you assign directly to a variable, you are not modifying any objects, merely repointing your variable to a different object.
But assigning a property, like a.foo, will modify the object that a points to. This, of course, also modifies all other references that point to this object simply because they all point to the same object.
Your question has already been satisfyingly answered by Squeegy - it has nothing to do with objects vs. primitives, but with reassignment of variables vs. setting properties in the same referenced object.
There seems to be a lot of confusion about JavaScript types in the answers and comments, so here's a small introduction to JavaScript's type system:
In JavaScript, there are two fundamentally different kinds of values: primitives and objects (and there is no thing like a 'hash').
Strings, numbers and booleans as well as null and undefined are primitives, objects are everything which can have properties. Even arrays and functions are regular objects and therefore can hold arbitrary properties. They just differ in the internal [[Class]] property (functions additionally have a property called [[Call]] and [[Construct]], but hey, that's details).
The reason that primitive values may behave like objects is because of autoboxing, but the primitives themselves can't hold any properties.
Here is an example:
var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
This will output undefined: a holds a primitive value, which gets promoted to an object when assigning the property foo. But this new object is immediately discarded, so the value of foo is lost.
Think of it like this:
var a = 'quux';
new String(a).foo = 'bar'; // we never save this new object anywhere!
document.writeln(new String(a).foo); // a completly new object gets created
You're more or less correct except that what you're referring to as a "hash" is actually just shorthand syntax for an Object.
In the first example, a and b both refer to the same object. In the second example, you change a to refer to something else.
here is my version of the answer:
obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"
// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"
// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory
You are setting a to point to a new string object, while b keeps pointing to the old string object.
In the first case you change some property of the object contained in the variable, in the second case you assign a new value to the variable. That are fundamentally different things. The variables a and b are not somehow magically linked by the first assignment, they just contain the same object. That's also the case in the second example, until you assign a new value to the b variable.
The difference is between simple types and objects.
Anything that's an object (like an array or a function) is passed by reference.
Anything that's a simple type (like a string or a number) is copied.
I always have a copyArray function handy so I can be sure I'm not creating a bunch of aliases to the same array.
I've been reading tutorials for a few weeks now and I've just figured out that when I use the prototype property on a constructor function, the key/value pairs on that prototype property are copied to the proto property of the newly instantiated object.
function F(){};
F.prototype.k = "v";
console.dir(F.k)//logs "undefined"
console.dir(F.prototype.k)//logs "v"
var o = new F;
console.dir(o.k)//logs "v"
So, key "k" is on the prototype property in the constructor and then transfers this to the proto property of newly instantiated object "o" which is why it can be accessed as if it were just a normal key/value pair on the object. Ok, that makes sense to me...but I thought about it and I've seen people use the new keyword for built-in things like String (although this is usually not done)
var s = new String;
the above code is an example of the way a new string item could be created the same way objects can be instantiated based on constructor functions. This made me wonder "is String just a constructor function????!" So I tested this out:
console.dir(String.prototype)
And I got a whole list of exactly the same properties that are attached to s. So, is "String" just a constructor function? The same behavior seems to be true of these items:
console.dir(String.prototype);
console.dir(Number.prototype);
console.dir(Boolean.prototype);
console.dir(Array.prototype);
console.dir(Object.prototype);
console.dir(Function.prototype);
console.dir(Date.prototype);
They all appear to behave exactly the same as constructor functions. They are even all capitalized rather than camelcase. Are they just constructor functions with a few built-in bells and whistles added to them?
There are 6 data types in JavaScript:
Boolean
Number
String
Null
Undefined
Object
The first five are so called primitive types. Three of the primitive types, Boolean, Number and String, also have an equivalent Object implementation.
Whenever you use (Boolean|Number|String) literals, you are creating a value of that corresponding type.
You can also create Boolean, Number and String objects by calling the corresponding constructor function with the new operator:
var s = 'foo'; // type string
var s2 = new String('foo'); // type object
Now, the reason why you can access properties on both of them is that JavaScript auto-boxes primitive values. I.e. when you are trying to access a property on a primitive value, it will temporarily convert the value to an object and access the property.
So
var v = "foo";
alert(v.length);
is essentially
var v = "foo";
alert((new String(v)).length);
If the String, Number or Boolean function is called without the new keyword, they will return a primitive value instead, which makes them act as conversion functions.
And to round this up: Every function has a prototype property, every function can potentially act as a constructor. Whether it really does depends on the implementation of the function.
This question already has answers here:
Legitimate uses of Object(o)
(2 answers)
Closed 8 years ago.
Snippet from underscore.js for testing object
_.isObject = function(obj) {
return obj === Object(obj);
};
What exactly is this doing that makes it check for the type?
A jsperf shows that this is faster than using a conventional check, that is why it is used.
The Object constructor creates an object wrapper for the given value. If the value is null or undefined, it will create and return an empty object, otherwise, it will return an object of a type that corresponds to the given value.
Source
What does Object(obj) do?
Read the EcmaScript spec on The Object Constructor Called as a Function and the abstract ToObject operation.
What exactly is this doing that makes it check for the type?
Object(obj) will only yield an object that is strictly equal (===) to obj (i.e the same reference as the input) when the input was a non-primitive value (null, booleans, strings, numbers, undefined), i.e. an EcmaScript Object (including String/Boolean/Number/Array instances, functions, other objects).
I can't find the relevant documentation, but it appears that the Object function either returns a new object that wraps the passed in value or returns the argument if it's already an object; otherwise, the === test would always return false.
Object(5) === 5 // false, Object(5) creates Number object
Object(null) === null // false, Object(null) creates an empty object
var foo = { prop: 'value' };
Object(foo) === foo // true!? Argument is not wrapped
It appears that this behavior works to test if a value is an object.
Update
It appears that this is in the spec:
When the Object function is called with no arguments or with one argument value, the following steps are taken:
1. If value is null, undefined or not supplied, create and return a new Object object exactly as if the standard built-in Object constructor had been called with the same arguments (15.2.2.1).
2. Return ToObject(value).
And ToObject's "result is the input object" is also defined in the spec.
Javascript seems to take a few liberties when it comes to its built-in types and objects.
To get at the functions inside the Array type you can do this:
> Array().slice
function slice() {
[native code]
}
So here Array looks like a standard function that is being used as a constructor. Except... slice is not a member function of the Array() function, it's a member function of the Array object.
Another unusual thing about Array() is it seems to return an Array object whether you call it with new() or not:
> var a = Array()
undefined
> a
[]
> a.length
0
> var b = new Array()
undefined
> b
[]
> b.length
0
Math on the other hand seems to be a built in singleton object that is always present (ie: no need to instantiate). So you would use Math.min.apply while with Array using Array().slice.apply.
My question is what makes Array() so different than either a constructor you would write yourself and the other built-in objects of Javascript.
I'll make some comments inline, quoting your question:
Except... slice is not a member function of the Array() function, it's a member function of the Array object.
More exactly, slice is a member of the Array.prototype object, by executing Array(), you are creating a new array object, that inherits from Array.prototype, that's why slice is available.
Another unusual thing about Array() is it seems to return an Array object whether you call it with new() or not:
This behavior is shared also by other built-in constructors, for example Function:
var fn = Function('return "foo";');
Is equivalent to:
var fn = new Function('return "foo";');
The cases are described in the specification (The Array constructor called as a function vs new Array), although other constructors present a different behavior when you use them with or without new, for example, the primitive wrappers:
new Number("20"); // produces a Number object
typeof new Number("20"); // "object"
Number("20"); // makes type conversion
typeof Number("20"); // "number"
Math on the other hand seems to be a built in singleton object that is always present (ie: no need to instantiate). So you would use Math.min.apply while with Array using Array().slice.apply.
Yes, Math is a simple object, not a function like Array.
It inherits from Object.prototype and IIRC the only peculiar difference that it has with a simple user-defined object is that it's internal [[Class]] property contains "Math", e.g.:
Object.prototype.toString.call(Math); // "[object Math]"
My question is what makes Array() so different than either a constructor you would write yourself and the other built-in objects of Javascript.
Array isn't that different, you could write a constructor that behaves the same way if invoked with new or not, for example:
function Foo (arg) {
if (!(this instanceof Foo)) { return new Foo(arg); }
this.foo = arg;
}
new Foo('bar'); // { foo: 'bar' }
Foo('bar'); // { foo: 'bar' }
You're writing
Array().slice()
What that means is:
Call the "Array" function
Look for a property called "slice" on the return value
Treat the value of that property as a reference to a function, and call it
The "slice" function is defined on the Array prototype object, which means that every instance of Array has access to it via that property name. The key here is that the "Array function" as you call it is referenced by the symbol "Array". When you write "Array()", that means to call the function, and thus that expression refers to an array instance. There's not really much difference between a constructor and a regular function; really, it's the new keyword that makes a difference by altering the way that the function is invoked (that is, with a freshly-created Object instance as the this context value). A function is free to check to see if this refers to the global object, and if so to return a newly-created object on its own initiative.
The "Math" object is just an object; you can think of it as being defined like this:
var Math = {
min: function(n1, n2) { ... },
max: function(n1, n2) { ... },
// ...
};