I am very confused about how constructors work in Javascrpt; despite using the language for several years (mostly as if it were like a semi-imperative version of LISP) I would like to know more about how objects are supposed to work in it.
Given this code:
function Foo(x) {
return {
bar: function() { return x; }
};
}
What is the difference between calling myFoo = Foo(5)
and myFoo = new Foo(5)
? Or, in other words, what exactly does a constructor in Javascript do?
New keyword in JavaScript is used to create an instance of an object that has a constructor function. On calling the constructor function with 'new' operator, the following actions are taken: A new empty object is created.
The new keyword in JavaScript: The new keyword is used to create an instance of a user-defined object type and a constructor function. It is used to constructs and returns an object of the constructor function.
It's because a <label> with a for attribute raises the click event of <input type="checkbox"> element that is associated for when clicked. You should bind click event handler to input , not to label . Show activity on this post. When you click your label, may it be there is event click runs also on checkbox?
What is the difference between calling
myFoo = Foo(5)
andmyFoo = new Foo(5)
?
There's no difference for that code, because it returns an object, and the spec says:
- Let result be the result of calling the [[Call]] internal property of F, providing obj as the
this
value and providing the argument list passed into [[Construct]] as args.- If
Type(result)
isObject
then return result.
Since that function returns a result that is an Object, its result is used. You would notice a difference if it did not return an object, or if it checked this
, for example if you rewrote it as:
function Foo(x) {
if (!(this instanceof Foo)) { return new Foo(x); }
this.bar = function() { return x; };
}
// Now instanceof works.
alert((new Foo) instanceof Foo);
What does
new
in JavaScript do, anyway?
The new
operator causes the function to be called with this
bound to a newly created Object
whose prototype is that function's prototype
property.
For user-defined functions,
new f(a, b, c)
is equivalent to
// Create a new instance using f's prototype.
var newInstance = Object.create(f.prototype), result;
// Call the function
result = f.call(newInstance, a, b, c),
// If the result is a non-null object, use it, otherwise use the new instance.
result && typeof result === 'object' ? result : newInstance
Note, that the language specification actually defines functions with two operations, [[Call]] and [[Construct]], so there are some corner cases where new
behaves oddly.
For example, bound and built-in functions:
var g = f.call.bind(f);
should define a function that when called, just calls f
, so g
should be the same as f
in all respects, but
new g()
produces
TypeError: function call() { [native code] } is not a constructor
because the builtin function Function.prototype.call
supports [[Call]] but not [[Construct]].
Function.prototype.bind
also behaves differently around new
and regular calls. The this
value is always the bound thisValue when called, but is a newly constructed instance when you use new
.
In this particular example, there's no difference in the end result.
This is because your Foo
function is returning an object instance.
The new
operator returns a newly created object that inherits from the constructor's prototype only when the function returns a primitive value (or it doesn't return anything, which is technically the undefined
value).
For example:
function Foo () {
return 5; // or "", or null, or no return statement at all (undefined)
}
var foo = new Foo();
typeof foo; // "object"
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
When you return an object, the newly created object that inherits from the constructor's prototype is simply discarded:
function Foo () {
return {};
}
var foo = new Foo();
typeof foo; // "object"
foo instanceof Foo; // false
Foo.prototype.isPrototypeOf(foo); // false
See also:
In this instance there will be no difference as you are returning a new object. It could be rewritten as:
function Foo(x){
this._x = x;
}
Foo.prototype.bar = function() {
return this._x;
}
With this syntax each time you call new Foo
it will create a new object with a property of _x
. The benefit is that the bar
function will be stored once and reused for multiple instances of Foo. With the code in the question calling Foo()
multiple times will create a bar function for every instance. So attaching functions to the prototype rather than having them directly on the object will be lighter in memory.
A full break down of how the prototype works can be found at MDC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With