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".
Related
I created a class using function like -
function Person(name) {
this.name = name;
}
var obj = new Person("Ferdinand");
console.log(obj.name);
I am creating an object obj and prints its property name it is working fine and prints "Ferdinand", but if we forget to write new key word like below program -
function Person(name) {
this.name = name;
}
var obj = Person("Ferdinand");
console.log(name);
Here I am not able to understand why name is available in console, it is printing "Ferdinand". But we are using Person as a function and assigning name variable in function itself so why its value is available outside function.
JavaScript does not implement objects in the classical sense. Instead, they are implemented directly:
var thing={}; // new object
Because you typically want multiple objects to follow a common pattern and behaviour, you can use what is called a constructor function to help. In your example, Person is a constructor function.
When using a constructor, you call it indirectly using the new command:
var thing = new Person(…);
In fact, there’s a lot of magic going on here:
JavaScript begins by creating a new object: var thing={};.
Then the this key word is assigned to the new object
Finally the constructor is run, using the this value to assign local values.
If you call a constructor function directly, the first 2 steps do not apply, and the function is left trying to work in its own definition of this which is generally not what you want.
If you really want to call the constructor function without bothering with new, you can try the following:
function Person(data) {
// “new” safe constructor
if(!(this instanceof Person)) {
return new Person(data);
}
This new version checks whether it is being called as a proper constructor, and, if not, calls itself properly.
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.
What the different if both of them call the constructor "Array" and generate an object?
I know that we lost this if we create some object without new:
function Animal(name) {this.name = name}
var duck = Animal('duck'); // undefined
But how that works for new Array(n) and Array(n)?
There is no difference. Check this article:
You never need to use new Object() in JavaScript. Use the object
literal {} instead. Similarly, don’t use new Array(), use the array
literal [] instead. Arrays in JavaScript work nothing like the arrays
in Java, and use of the Java-like syntax will confuse you.
Do not use new Number, new String, or new Boolean. These forms produce
unnecessary object wrappers. Just use simple literals instead.
...............................
So the rule is simple: The only time we should use the new operator is
to invoke a pseudoclassical Constructor function. When calling a
Constructor function, the use of new is mandatory.
Such behaviour for Array is described in spec.
You can achive the same behaviour like this
function Animal(name) {
if(!(this instanceof Animal)) {
return new Animal(name);
}
this.name = name
}
var duck = Animal('duck'); //Animal {name: "duck"}
But a better idea would be to follow a simple code style convention that all functions starting with a captial letter are constructors and should be called with new. And set up a linter you prefer to check your code follows this rule.
JavaScript uses prototypal inheritance . When you use new command, It inherits from Object . Incase you want to inherit from an user defined object (e.g. Animal) you need to use new Animal() or without using new you can do it in following way.
// Function object acts as a combination of a prototype
// to use for the new object and a constructor function to invoke:
function Animal(name){
this.name = name
}
var inheritFrom = function(parent, prop){
// This is how you create object as a prototype of another object
// var x = {} syntax can’t do this as it always set the newly
//created object’s prototype to Object.prototype.
var obj = Object.create(parent.prototype);
// apply() method calls a function with a given this value
//and arguments provided as an array
parent.apply(obj, [prop]);
return obj
}
var duck = inheritFrom(Animal, 'duck');
console.log(duck.name); // ‘duck’
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 have seen the following style for returning a public interface from a constructor:
function AnObjectConstructor() {
function localFunc() {};
function publicFunc() {};
// public interface
var _this = {
publicFunc: publicFunc
};
return _this;
};
I like this style because the public interface is clearly in one place and also localFunc can access publicFunc without using _this
This code can also be written like this:
function AnObjectConstructor() {
function localFunc() {};
function publicFunc() {};
// public interface
var _this = this;
_this.publicFunc = publicFunc;
return _this;
};
Both these forms are intended to be used with new:
var obj = new AnObjectConstructor();
obj.publicFunc();
I am not clear on whether these two forms are the same or not, and was hoping someone can help me with that ?
Also any general comments on this style will be appreciated..
Those two snippets are not doing the same thing. While both snippets have public references to publicFunc the first snippet returns an object literal and the second a reference to the function. Neither examples are examples are how you would create a function constructor. You need to use the new keyword to instantiate an instance of an object:
function AnObjectConstructor() {
function localFunc() {};
function publicFunc() {};
// public interface
this.publicFunc = publicFunc;
//You don't need this line :return _this;
};
var obj = new AnObjectConstructor();
I also removed the creation of _this as there was no reason to create a local variable and assign this to it.
Edit
The second approach is preferred in my opinion, because it is the more conventional approach that leverages JavaScript's built-in capability of constructing objects. The first approach misses the point, because it is simply a function that returns a stripped down object literal.
There is a difference. Your first constructor function could be invoked in two ways:
var myObject = AnObjectConstructor();
or
var myObject = new AnObjectConstructor();
This is because the first constructor function manually creates the returned object. In the case of the new operator, the this object that is automatically created by engine is effectively discarded when you return your own hand-made object.
However, your second constructor function relies on you invoking it with the new operator. If you do not use new, it will pollute the current this which could be another object or global space.
When used with the new operator, they will indeed be the same (at least as far as how they're currently defined), as the specification says to set this to the newly constructed object when executing the constructor, or if an object is returned instead (your first example), to use that as the constructed object. The difference when returning your own object is that it won't have the [[prototype]] set to AnObjectConstructor.prototype.
In addition, if you call them without the new operator, then their behaviour will be very different. The first one will return a new object, much like a factory style method, but the second one will augment the global object, which is almost never what you want.