Is it possible to write a javascript function that follows this (valid) typescript interface:
interface Foo{
// constructor:
new (): string;
}
i.e. Something that when called with a new operator returns a string. e.g. the following will not work.
function foo(){
return "something";
}
var x = new foo();
// x is now foo (and not string) whether you like it or not :)
You should be able to do:
function foo(){
return new String("something");
}
var x = new foo();
console.log(x);
You can return any object, but literals don't work. See here: What values can a constructor return to avoid returning this?
ECMAScript 5's Section 13.2.2 (on the [[Construct]] internal property) has this to say about the return value of a constructor:
1) Let obj be a newly created native ECMAScript object.
...
8) 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.
9) If Type(result) is Object then return result.
10) Return obj.
Thus, the return value of a constructor can only be an object. A string primitive like "foo" has a Type result of String rather than Object. This means that step 9 is false, so step 10 returns the constructed object, instead of the return value of the constructor function.
Instead, you must return an object (new String("foo")), as detailed in RobH's answer.
Related
What are the exact circumstances for which a return statement in Javascript can return a value other than this when a constructor is invoked using the new keyword?
Example:
function Foo () {
return something;
}
var foo = new Foo ();
If I'm not mistaken, if something is a non-function primitive, this will be returned. Otherwise something is returned. Is this correct?
In other words, what values can something take to cause (new Foo () instanceof Foo) === false?
The exact condition is described on the [[Construct]] internal property, which is used by the new operator:
From the ECMA-262 3rd. Edition Specification:
13.2.2 [[Construct]]
When the [[Construct]] property for a Function object F is
called, the following steps are taken:
Create a new native ECMAScript object.
Set the [[Class]] property of Result(1) to "Object".
Get the value of the prototype property of F.
If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as
described in 15.2.3.1.
Invoke the [[Call]] property of F, providing Result(1) as the this value and
providing the argument list passed into [[Construct]] as the
argument values.
If Type(Result(6)) is
Object then return Result(6).
Return Result(1).
Look at steps 7 and 8, the new object will be returned only if the
type of Result(6) (the value returned from the F constructor
function) is not an Object.
Concrete examples
/*
ECMA 262 v 5
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
"4.3.2
primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
*/
var Person = function(x){
return x;
};
console.log(Person.constructor);
console.log(Person.prototype.constructor);
console.log(typeof(Person));
console.log(typeof(Person.prototype));
function log(x){
console.log(x instanceof Person);
console.log(typeof x);
console.log(typeof x.prototype);
}
log(new Person(undefined));
log(new Person(null));
log(new Person(true));
log(new Person(2));
log(new Person(""));
//returns a function not an object
log(new Person(function(){}));
//implementation?
//log(new Person(Symbol('%')));
I couldn't find any documentation on the matter, but I think you're correct. For example, you can return new Number(5) from a constructor, but not the literal 5 (which is ignored and this is returned instead).
As a side note, the return value or this is just part of the equation.
For example, consider this:
function Two() { return new Number(2); }
var two = new Two;
two + 2; // 4
two.valueOf = function() { return 3; }
two + 2; // 5
two.valueOf = function() { return '2'; }
two + 2; // '22'
As you can see, .valueOf() is internally used and can be exploited for fun and profit. You can even create side effects, for example:
function AutoIncrementingNumber(start) {
var n = new Number, val = start || 0;
n.valueOf = function() { return val++; };
return n;
}
var auto = new AutoIncrementingNumber(42);
auto + 1; // 43
auto + 1; // 44
auto + 1; // 45
I can imagine this must have some sort of practical application. And it doesn't have to be explicitly a Number either, if you add .valueOf to any object it can behave as a number:
({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638
You can exploit this to make an object that always returns a new GUID, for instance.
Trying to put a few points in simpler words.
In javascript, when you use a new keyword on a function and if,
function does not return anything, it will return an intended object
function User() {
this.name = 'Virat'
}
var user = new User();
console.log(user.name); //=> 'Virat'
function returns any truthy complex object [object, array, function etc], that complex object takes priority and user variable will hold the returned complex object
function User() {
this.name = 'Virat';
return function(){};
}
var user = new User();
console.log(user.name); //=> undefined
console.log(user); //=> function
function returns any literal, constructor takes priority and it will return an intended object
function User() {
this.name = 'Virat';
return 10;
}
var user = new User();
console.log(user.name); //=> 'Virat'
When you are using the new keyword, an object is created. Then the function is called to initialise the object.
There is nothing that the function can do to prevent the object being created, as that is done before the function is called.
If I return some value or object in constructor function, what will the var get?
function MyConstroctor()
{
//what in case when return 5;
//what in case when return someObject;
}
var n = new MyConstroctor();
what n will get in both cases?
Actually its a quiz question, what will be the answer?
What is returned from a custom object constructor?
a)The newly-instantiated object
b)undefined - constructors do not return values
c)Whatever is the return statement
d)Whatever is the return statement; the newly-instantiated object if no return statement
Short Answer
The constructor returns the this object.
function Car() {
this.num_wheels = 4;
}
// car = { num_wheels:4 };
var car = new Car();
Long Answer
By the Javascript spec, when a function is invoked with new, Javascript creates a new object, then sets the "constructor" property of that object to the function invoked, and finally assigns that object to the name this. You then have access to the this object from the body of the function.
Once the function body is executed, Javascript will return:
ANY object if the type of the returned value is object:
function Car(){
this.num_wheels = 4;
return { num_wheels:37 };
}
var car = new Car();
alert(car.num_wheels); // 37
The this object if the function has no return statement OR if the function returns a value of a type other than object:
function Car() {
this.num_wheels = 4;
return 'VROOM';
}
var car = new Car();
alert(car.num_wheels); // 4
alert(Car()); // No 'new', so the alert will show 'VROOM'
Basically if your constructor returns a primitive value, such as a string, number, boolean, null or undefined, (or you don't return anything which is equivalent to returning undefined), a newly created object that inherits from the constructor's prototype will be returned.
That's the object you have access with the this keyword inside the constructor when called with the new keyword.
For example:
function Test() {
return 5; // returning a primitive
}
var obj = new Test();
obj == 5; // false
obj instanceof Test; // true, it inherits from Test.prototype
Test.prototype.isPrototypeOf(obj); // true
But if the returned value is an object reference, that will be the returned value, e.g.:
function Test2() {
this.foo = ""; // the object referred by `this` will be lost...
return {foo: 'bar'};
}
var obj = new Test2();
obj.foo; // "bar"
If you are interested on the internals of the new operator, you can check the algorithm of the [[Construct]] internal operation, is the one responsible of creating the new object that inherits from the constructor's prototype, and to decide what to return:
13.2.2 [[Construct]]
When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:
Let obj be a newly created native ECMAScript object.
Set all the internal methods of obj as specified in 8.12.
Set the [[Class]] internal property of obj to "Object".
Set the [[Extensible]] internal property of obj to true.
Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
If Type(proto) is Object, set the[[Prototype]]` internal property of obj to proto.
If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
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) is Object then return result.
Return obj.
I found this great link:
JavaScript: Constructor Return Value
The second piece of magic eluded to above is the ability for a
constructor to return a specific, possibly pre-existing object, rather
than a reference to a new instance. This would allow you to manage the
number of actual instances yourself if needed; possibly for reasons of
limited resources or whatnot.
var g_deebee = new Deebee();
function Deebee() { return g_deebee; }
var db1 = new Deebee();
var db2 = new Deebee();
if (db1 != db2)
throw Error("JS constructor returned wrong object!");
else console.log('Equal');
It's as easy as it said in documentation (new operator) :
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. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
Trying to simplify the existing answers by providing discrete examples proving that:
Only constructors that return primitive or undefined implicitly create a new instance of themselves. Otherwise the exact object returned by the constructor is used as is.
Consider the following constructor that returns exactly what we pass to it. Check the usages:
//A constructor returning the passed value, or not returning at all.
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//no value passed (no value is returned from constructor)
console.log((new MyConstructor()) instanceof MyConstructor)
//true
//Primitive passed:
console.log((new MyConstructor(1)) instanceof MyConstructor)
//true
console.log((new MyConstructor(false)) instanceof MyConstructor)
//true
console.log((new MyConstructor("1")) instanceof MyConstructor)
//true
console.log((new MyConstructor(1.0)) instanceof MyConstructor)
//true
//Object passed
console.log((new MyConstructor(new Number(1))) instanceof MyConstructor)
//false
console.log((new MyConstructor({num:1})) instanceof MyConstructor)
//false
console.log((new MyConstructor([1])) instanceof MyConstructor)
//false
console.log((new MyConstructor(MyConstructor)) instanceof MyConstructor)
//false
//Same results if we use: MyConstructor.prototype.isPrototypeOf(new MyConstructor()) e.t.c..
The same rules as above apply also for class constructors. This means that, if the constructor does not return undefined or primitive, we can have the following, which might feel weird to people coming from java:
(new MyClass()) instanceof MyClass //false
Using the same constructor, check in practice how the instance is different when undefined or primitive is returned:
//As above
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//Same object passed (same instance to both variables)
let obj = {};
let a1 = new MyConstructor(obj)
let a2 = new MyConstructor(obj)
a1.x=1
a2.x=2
console.log(a1.x === a2.x, a1.x, a2.x)
//true 2 2
//undefined passed (different instance to each variable)
let b1 = new MyConstructor()
let b2 = new MyConstructor()
b1.x=1
b2.x=2
console.log(b1.x === b2.x, b1.x, b2.x)
//false 1 2
//Primitive passed (different instance to each variable)
let c1 = new MyConstructor(5)
let c2 = new MyConstructor(5)
c1.x=1
c2.x=2
console.log(c1.x === c2.x, c1.x, c2.x)
//false 1 2
Additional note: Sometimes a function could act as a constructor even if it is not called as a constructor:
function F(){
//If not called as a constructor, call as a constructor and return the result
if(!new.target){
return new F();
}
}
console.log(F() instanceof F)
//true
console.log(new F() instanceof F)
//true
You shouldn't return anything in a constructor. A constructor is used to initialize the object. In case you want to know what happens is that if you return 5 then n will simply be an empty object and if you return for example { a: 5 }, then n will have a property a=5.
To answer your specific question:
function MyConstructor()
{
return 5;
}
var n = new MyConstructor();
n is an object instance of MyConstructor.
function SomeObject(name) {
this.name = name;
this.shout = function() {
alert("Hello " + this.name)
}
}
function MyConstructor()
{
return new SomeObject("coure06");
}
var n = new MyConstructor();
n.shout();
n is an instance of SomeObject (call n.shout() to prove it)
To make this all absolutely clear...
1) If you return a primitive type, like a number or a string, it will be ignored.
2) Otherwise, you will pass back the object
Functions and constructors are exactly the same in JavaScript, but how you call them changes their behaviour. A quick example of this is below...
function AddTwoNumbers(first, second) {
return first + second;
}
var functionCall = AddTwoNumbers(5, 3);
alert(functionCall);// 8
var constructorCall = new AddTwoNumbers(5, 3);
alert(constructorCall);// object
I've read the topic about "new" keyword in javascript (What is the 'new' keyword in JavaScript?). But, i'm still in the fog; let's talk about this example :
var foo = function() {
return {
setA: function(a) {
this.a = a;
},
readA: function() {
console.log(this.a);
}
};
};
And now what's about these two pieces of code :
One:
var bob1 = foo();
bob1.setA(10);
bob1.readA();
Two:
var bob2 = new foo();
bob2.setA(10);
bob2.readA();
I cannot see any differences at my level. So what is the gain to use the keyword "new" ?
If your function returns object directly, then you do not need an new operator.
The new keys does more than that.
Lets say
function Animal(kind, name) {
this.kind = kind;
this.name = name;
}
Animal.prototype.walk = function() {
console.log('Walking');
}
Then you are doing
var animal = new Animal();
Javascript engine will do following things
var o = Object.create(Animal.prototype)
Animal.apply(o, arguments);
return o;
Object.create will do the prototype inheritance of the prototype object of Animal function. So animal object will have its own properties and its inherited property.
i'm still in the fog about new; let's talk about this example :
var foo = function() {
return {
setA: function(a) {
this.a = a;
},
readA: function() {
console.log(this.a);
}
};
};
We shouldn't talk about this example. Whether or not we use new with this function does not make a difference, because of the way new works:
A new object is created, inheriting from foo.prototype.
The constructor function foo is called with the specified arguments and this bound
to
the newly created object.
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. (Normally constructors don't return a value, but they can
choose to do so if they want to override the normal object creation
process.)
Step 3 is the thing to look at here. You're creating and returning an object (the object literal), so that will become assigned to bob1. Usually, constructor functions do not return anything, and the new instance that is implicitly created in step1 (and available inside the function as this) becomes the result.
Both new foo() and foo() do only assign your object literal to the bob variable - no difference in the result. The instance created by the new is totally ignored by your code. It would be different in the following examples:
function foo() {
this.setA = function(a) {
this.a = a;
};
this.readA = function() {
console.log(this.a);
};
// return this; is implicit
}
var bob = new foo; // OK
var bob = foo(); // horrible error
If the constructor function foo returns an object, then new foo() is identical to calling the function foo() directly. We can prove this is so by examining the ECMAScript behavior for new:
Return the result of calling the [[Construct]] internal method on constructor [i.e., the constructor function]...
The [[Construct]] internal method of a function is a special wrapper for calling the function's [[Call]] internal method (which is just the function's normal behavior). Let's see the end of [[Construct]] to see how this wrapper behaves:
8) Let result be the result of calling the [[Call]] internal property of F [the function invoked by new], providing obj as the this value and providing the argument list passed into [[Construct]] as args.
9) If Type(result) is Object then return result.
10) Return obj.
In your case, your constructor function foo returns an object, so step 9 of [[Construct]] (and therefore, in turn, new foo()) returns that object. But we see in step 10 that [[Construct]] could return some other value called obj, which is equal to the this value inside the constructor. Let's rewind and see what that's all about:
1) Let obj be a newly created native ECMAScript object.
...
4) Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
5) If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
Here we see the real power of new: if the constructor function does not return an object (and therefore the [[Construct]] operation launched by new is allowed to return obj), then prototypal inheritance takes place. The [[Prototype]] of obj (a.k.a. obj.__proto__) is set to the prototype property of the constructor method. This means that if foo doesn't return an object (and instead modifies this), and foo.prototype.someProp is set, then an instance returned from var instance = new foo() will have access to instance.someProp.
Thus, a different way to write your code might be:
var foo = function() { };
foo.prototype.setA = function(a) { this.a = a; };
foo.prototype.setA = function(a) { console.log(this.a); };
In this case, new foo() produces an object whose prototype chain includes foo.prototype, while foo() does not. This has the benefit of lower memory use: all foo instances here share common prototypal methods, instead of having each instance carry its own separate functions.
I'am new in javascript.
I can't understand why the function returns T1 object (not just string 'hi') in the following example.
function T1(){
return 'hi';
}
function T(){
return new T1();
}
T();
output: T1
And returns function in the following example
function T1(){
return function(){ return 'hi'; }
}
function T(){
return new T1();
}
T();
output: function (){ return 'hi' }
Why does the first example returns an object (not the string "hi", what is expected to happen) and the second returns the function body that is returned from the first function (not the expected object)?
Please explain this result. Thank you)
The new operator returns the object created by the operator unless the constructor function returns a different object. Any non-object return value of the constructor function is ignored, which is why when you return hi you don't see this.
Section 13.2.2 ("[[Construct]]") of the specification, which is referenced by Section 11.2.2 ("The new operator").
The new keyword. That makes an object.
function T1(){
return 'hi';
}
function T(){
return T1();
}
T(); // 'hi'
JavaScript objects should be like this:
function T1(){
this.test = function(){
return 'hi';
};
}
function T(){
return new T1();
}
var test = T(); // T1 object
test.test(); // 'hi'
In your code:
> function T1() {
> return 'hi';
> }
A function called as a constructor will always return an object, it won't return a string. So when called simply as a function, T1 will return the string 'hi', but when called as a constructor, it iwll return a new T1 instance. Since that instance isn't assigned any properties, nor does T1.prototype seem to have any, it will be almost indistinguishable from an object created using new Object().
It will be an instanceof T1 and its constructor property will reference T1.
> function T() {
> return new T1();
> }
By convention, only constructors start with a capital letter (except for constants, which might be all capitals).
> T();
The T function simply returns a new T1 object, which is not assigned to anything so can't be referenced or called, so it's immediately available for garbage collection. It has not special methods or properties.
var t = T(); // returns a new T1 instance
t(); // throws an error since t is a plain object,
// not a function and so can't be called.
Edit
Since the question was changed:
function T1() {
return function(){ return 'hi'; }
}
In this case, when T1 is called as a constructor, the return statement returns a function, which is an Object (all functions are objects), so that is what is returned.
The function is returned in the second example because you returned an anonimous function on T1() and so, you can execute it placing a pair of parentesis () in front of if:
function T1(){
return function(){ return 'hi'; }
}
function T(){
return new T1();
}
T()(); // hi
// or
var T2 = T();
T2(); // hi
This is not a bug, its a powerfull feature from JS.
Just remember of "Spiderman" frase:
With great powers cames great responsabilities.
Edit:
Now I see the real question: Why does the first example returns an object (not the string "hi", what is expected to happen) and the second returns the function body that is returned from the first function (not the expected object)?
This seems a bug to me, but maybe by design, since functions and objects returned can be used and a workaroud with a parameter is easy to do.
What are the exact circumstances for which a return statement in Javascript can return a value other than this when a constructor is invoked using the new keyword?
Example:
function Foo () {
return something;
}
var foo = new Foo ();
If I'm not mistaken, if something is a non-function primitive, this will be returned. Otherwise something is returned. Is this correct?
In other words, what values can something take to cause (new Foo () instanceof Foo) === false?
The exact condition is described on the [[Construct]] internal property, which is used by the new operator:
From the ECMA-262 3rd. Edition Specification:
13.2.2 [[Construct]]
When the [[Construct]] property for a Function object F is
called, the following steps are taken:
Create a new native ECMAScript object.
Set the [[Class]] property of Result(1) to "Object".
Get the value of the prototype property of F.
If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as
described in 15.2.3.1.
Invoke the [[Call]] property of F, providing Result(1) as the this value and
providing the argument list passed into [[Construct]] as the
argument values.
If Type(Result(6)) is
Object then return Result(6).
Return Result(1).
Look at steps 7 and 8, the new object will be returned only if the
type of Result(6) (the value returned from the F constructor
function) is not an Object.
Concrete examples
/*
ECMA 262 v 5
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
"4.3.2
primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
*/
var Person = function(x){
return x;
};
console.log(Person.constructor);
console.log(Person.prototype.constructor);
console.log(typeof(Person));
console.log(typeof(Person.prototype));
function log(x){
console.log(x instanceof Person);
console.log(typeof x);
console.log(typeof x.prototype);
}
log(new Person(undefined));
log(new Person(null));
log(new Person(true));
log(new Person(2));
log(new Person(""));
//returns a function not an object
log(new Person(function(){}));
//implementation?
//log(new Person(Symbol('%')));
I couldn't find any documentation on the matter, but I think you're correct. For example, you can return new Number(5) from a constructor, but not the literal 5 (which is ignored and this is returned instead).
As a side note, the return value or this is just part of the equation.
For example, consider this:
function Two() { return new Number(2); }
var two = new Two;
two + 2; // 4
two.valueOf = function() { return 3; }
two + 2; // 5
two.valueOf = function() { return '2'; }
two + 2; // '22'
As you can see, .valueOf() is internally used and can be exploited for fun and profit. You can even create side effects, for example:
function AutoIncrementingNumber(start) {
var n = new Number, val = start || 0;
n.valueOf = function() { return val++; };
return n;
}
var auto = new AutoIncrementingNumber(42);
auto + 1; // 43
auto + 1; // 44
auto + 1; // 45
I can imagine this must have some sort of practical application. And it doesn't have to be explicitly a Number either, if you add .valueOf to any object it can behave as a number:
({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638
You can exploit this to make an object that always returns a new GUID, for instance.
Trying to put a few points in simpler words.
In javascript, when you use a new keyword on a function and if,
function does not return anything, it will return an intended object
function User() {
this.name = 'Virat'
}
var user = new User();
console.log(user.name); //=> 'Virat'
function returns any truthy complex object [object, array, function etc], that complex object takes priority and user variable will hold the returned complex object
function User() {
this.name = 'Virat';
return function(){};
}
var user = new User();
console.log(user.name); //=> undefined
console.log(user); //=> function
function returns any literal, constructor takes priority and it will return an intended object
function User() {
this.name = 'Virat';
return 10;
}
var user = new User();
console.log(user.name); //=> 'Virat'
When you are using the new keyword, an object is created. Then the function is called to initialise the object.
There is nothing that the function can do to prevent the object being created, as that is done before the function is called.