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
thisvalue and providing the argument list passed into [[Construct]] as args.- If
Type(result)isObjectthen 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
newin 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