My question is regarding the resulting object from using new function(){ ... } over new Function();
My understanding so far/assumption
When we create a function using Function() or new Function() we get a object configured as a function (it's internal slots indicate a function type object)
With or without the new operator, the Function() constructor returns a new function object
Using a function expression returns a function object which internally uses the Function() constructor
A function expression provides optimization with parsing the function body
My question
Following my assumption above, why does new Function(); and new function(){ ... } return different things?
The first returns a function object, but the latter returns a standard object. Given that a function expression under the hood uses the Function() constructor, why does the latter not behave the same as new Function();?
Using new function(){ ...} I would expect a function object, not a standard object.
The following lines are essentially the same:
function foo(...) {...}
var foo = function (...) {...};
var foo = new Function (...);
They all declare a new function (which is an object, that is an instance of Function, which inherits the Object prototype, ...) in the current scope which can be accessed via the foo variable.
The new keyword instantiates an object from a function which allows you to create something similar to a class instance in a standard OOP language.
Continuing the example from above:
var bar = new foo(...)
would instantiate an instance of the foo function in the current scope which could be accessed via the bar variable.
why does new Function(); and new function(){ ... } return different things?
I'm going to rephrase the example slightly. Instead of:
new Function()
//and
new function(){ ... }
I'm going to use
new Function()
//and
var foo = function () { ... };
new foo();
The reason that new Function() returns a different thing than new foo() is entirely because Function is a different function from foo.
I expect that you're not confused by the fact that new Object() returns a different object with different features than new Array(). The exact same thing is happening here.
Given that a function expression under the hood uses the Function() constructor, why does the latter not behave the same as new Function();?
under the hood the later expression is essentially:
new (new Function ( ... ))
new Function(...) returns a new function, while new function() {...} returns a new Object.
Basically, Function is just a way to evaluate a piece of code.
Objects are a way, to store data in javascript.
Side note: you can technically do
new (new Function(...))
wich returns a new object.
Related
I have a function for creating objects as follows:
function person() {
this.name = "test person";
}
var me = new person();
Now I'm planning to wrap this function into another one like this for assertion purposes.
function reliable_person() {
/* do check on params if any*/
return new person();
}
var me = new reliable_person();
Is this a possible approach? I know there are better ways for such checks within the constructor itself, but is this a reliable solution?
Invoking a function with new constructs a new object and uses the given function to initialise the object. Something that's a bit special about this is that if you return a non-primitive value, like an object, from that function, that value will be used as the new object instead. Sounds complicated, but what it boils down to is that reliable_person() and new reliable_person() result in the exact same thing, because you're returning an object from it. So using new with that function is pointless.
Removing the superfluous new from it, all that's left is a normal function which returns an object (a "factory function"). Yes, that works and is "reliable".
Having this:
sillyObject = {
init: function init(sillySettings) {
name = sillySettings.name
}
};
sillyObject.showAlert = function(x) {
return alert(x);
};
When I run this code:
var sillyvar = new sillyObject()
sillyvar.init(mySettings);
silly.showAlert("silly!");
I get an error but instead if I run the same thing using Object.create it runs..
var sillyvar = Object.create(sillyObject);
sillyvar.init(mySettings);
silly.showAlert("silly!");
Any (silly) help will be appreciated.
new and Object.create are two fundamentally different things.
new is going to expect to be followed by a function, and if not (as you saw) it will give you an error. That is because new expects to call a constructor function and then use that as a basis for a new execution context. During that context, the function has this bound to the scope of the execution context. Once the function is done executing it returns the this value which usually has had some data attached to it. In your example, that would look like this:
function sillyObject() {}
sillyObject.prototype.init = function(sillySettings) {
//perhaps you wanted to attach this name to the sillyObject?
name = sillySettings.name;
//which would look like this
this.name = sillySettings.name;
//because `this` here refers to the object context (remember?)
};
sillyObject.prototype.showAlert = function(x){
return alert(x);//returning alert simply returns undefined (not sure why this is used here)
};
and then you could use new, it would create the execution context using the constructor and then attach the prototype and you would end up with a new instance of sillyObject (all instances would be different).
var sO = new sillyObject();
sO.init(mySettings);
sO.showAlert("silly!");
Object.create() on the other hand is expecting an object as an argument (which is why your version worked here). It will create a new object using that object argument as a template basically. Or as MDN explains it "The Object.create() method creates a new object with the specified prototype object and properties". This basically creates a copy if nothing else is done with the Object, and that is why the alert worked here but not in the new version.
If you tried doing new sillyObject(), the error you get is Uncaught TypeError: object is not a function since sillyObject is an object and not a function.
This answer gives a good overview on the new keyword.
Object.create does not do the same thing as new. It will create a new object with sillyObject as the prototype.
sillyObject is a Object not a function. new will create a new instance of a function. You probably want to use this or just .prototype
var sillyObject = function () {
this.sillySettings = {};
}
sillyObject.prototype = {
init : function (name) {
this.sillySettings.name = name;
},
showAlert: function (x) {
return alert(x);
}
};
var silly = new sillyObject();
silly.init('foo');
silly.showAlert('bar');
this.sillySettings isn't a function so we don't keep it in the prototype. We can keep init and showAlert in the prototype. We use prototype because when using new we use sillyObject() so imagine the variable silly being replaced this sillyObject() showing why we use prototype because silly is instantiated as a function.
The mere declaration of a function to an object leads to its invocation
var a = {};
a.xyz = new function() {
alert("dosomething");
}
I would expect, that the declared function a.xyz only gets invoked when I call it:
a.xyz();
What is wrong with my assumption?
Remove new and everything will be fine:
var a = {};
a.xyz = function() {
alert("dosomething");
}
JSFiddle: http://jsfiddle.net/vnj8pzm1/
EDIT: More about IIFE - Immediately-Invoked Function Expression (IIFE)
When you put new in front of your function definition, your function is being called as a constructor immediately.
As iceless mentioned, you should not have new in front of your function defintion. However, what iceless mentioned in the comment is incorrect
new function() {} or new function() {}(); will invoke the function just like function() {}(); or (function() {}());
new function() {} will create a new instance of an anonymous type, so in your code a.xyz is an object
if you change it to just function(){}() it would execute the function immediately and return nothing. See http://jsfiddle.net/mendesjuan/kzhg9ggu/
In short:
The new operator create an instance of the object with new, and that's why is executed right after the declaration.
In not so short
xyz= function(){};
Places a reference to an anonymous function into xyz and points to a function.
xyz= new function(){};
Places a reference to a newly constructed instance of an anonymous constructor function, so it will points to an object. Try typeof new function(){} and you will get object.
When the code new function(){alert('foo');} is executed, the following things happen:
A new object is created
The constructor function is called with the specified arguments and this bound to the newly created object. If no argument list is specified, function() is called without arguments.
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead.
I'm not understanding why in the following code, obj.BaseMethod doesn't return the method defined in BaseClass constructor. In other words, why is it that
SubClass.prototype.BaseMethod
is defined, but
new SubClass().prototype.BaseMethod
is undefined.
http://jsfiddle.net/HvxJ4/4/
I'm obviously missing something important here.
function BaseClass() {
var privatestuff = "blah";
return {
BaseMethod: function() {
console.log('BaseMethod called');
}
}
}
function SubClass() {
var moreprivates = "stuff";
return {
SubClassMethod: function() {
console.log('SubClassMethod called');
}
}
}
SubClass.prototype = new BaseClass();
var obj = new SubClass();
obj.SubClassMethod(); // SubClassMethod called
obj.BaseMethod(); // Uncaught TypeError: undefined is not a function
UPDATE
I actually understood how to get my code working using
this.method = function() { }
in my constructor function. I just didn't understand why the code above didn't do the same thing.
The answer is that if you return an object in a constructor function, you are no longer using "protoypal" inheritance.
The thing that makes this most clear to me was this answer
https://stackoverflow.com/a/2118831/834770
Quoting Douglas Crockford in Chapter 5, Inheritance, of JavaScript:
(...)
Douglas Crockford then explains how the new operator could be
implemented as a JavaScript function. This function makes use of
several other functions defined in the book, so I rewrote it in a
(somewhat) simpler form below:
function createNew(constructor) {
// a function to explain the new operator:
// var object = createNew(constructor);
// is equivalent to
// var object = new constructor();
//
// param: constructor, a function
// return: a new instance of the "constructor" kind of objects
// step 1. create a new empty object instance
// linked to the prototype of provided constructor
var hiddenLink = function(){};
hiddenLink.prototype = constructor.prototype;
var instance = new hiddenLink(); // cheap trick here: using new to implement new
// step 2. apply the constructor the new instance and get the result
var result = constructor.apply(instance); // make this a reference to instance within constructor
// step 3. check the result, and choose whether to return it or the created instance
if (typeof result === 'object') {
return object;
} else {
return instance;
}
}
So, in short, if you return an object in this function, then the inheritance bit is effectively ignored.
Here's a way to think of the statement
new SubClass().prototype.BaseMethod
First, the new keyword tells JavaScript to create a new, empty object, i.e. {}
Then JavaScript sets the context (this) to be equal to that new object and calls the function after new. So in this case JavaScript will look for a function to call, but your syntax doesn't reference a defined function, so the result is undefined.
Contrast that with a typical approach for defining objects in JavaScript:
function ExampleObject() {
// stuff related to the example object
this.exampleProperty = "value";
}
var exObj = new ExampleOject();
In this case new creates the empty object {} as before, but now there is a defined function to call. When this function is called, the newly created object (set equal to this) will have an exampleProperty set equal to "value". The resulting object is then assigned to the variable exObj.
It may sound strange to those coming from a Java background (or similar), but JavaScript doesn't really support the concept of classes. The language made the unfortunate choice of trying to make it's prototypical inheritance look like classical inheritance, but it's really not the same. If you're going to be spending a lot of time in JavaScript, you might want to stop trying to think in terms of classes and subclasses and learn a bit about prototypes instead.
I'm trying to understand some code Mozilla put out on constructor chaining. I've added comments to the parts I think I understand, but I'm still not clear on everything that's going on here. Can someone explain line by line what is going on in this code?
// Using apply() to chain constructors.
Function.prototype.construct = function (aArgs) {
// What is this line of code doing?
var fConstructor = this, fNewConstr = function () { fConstructor.apply(this, aArgs); };
// Assign the function prototype to the new function constructor's prototype.
fNewConstr.prototype = fConstructor.prototype;
// Return the new function constructor.
return new fNewConstr();
};
// Example usage.
function MyConstructor () {
// Iterate through the arguments passed into the constructor and add them as properties.
for (var nProp = 0; nProp < arguments.length; nProp++) {
this["property" + nProp] = arguments[nProp];
}
}
var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
// alerts "Hello world!"
alert(myInstance.property1);
// alerts "true"
alert(myInstance instanceof MyConstructor);
// alerts "MyConstructor"
alert(myInstance.constructor);
The original code can be found here.
Basically, this is an alternate way to call a constructor function, which gives you the opportunity to wrap the constructor call in another function. I'll focus on the line you are confused about. fConstructor is set to this, which references our original constructor function, in this example that is MyConstructor. fNewConstr is the constructor which will override the original constructor. Within that fNewConstr you could implement additional code not found in the MyConstructor. Within fNewConstr, we call fConstructor using the Function apply method, passing this as the context, and the aArgs array passed to the construct method. Then we set the prototype of the fNewConstr to the fConstructor prototype to complete the inheritance chain. Finally, we return a new instance of fNewConstr. Prefixing the new keyword to a function call creates a new object, sets its prototype to the prototype of the function, and invokes the function in the context of the new item. Because we apply the fConstructor method with the fNewConstr's context, the result is essentially the same as calling new MyConstructor(). Make sense? Or do I need to go into more detail.