Strange behaviour of Javascript `new` from `function` [duplicate] - javascript

This question already has answers here:
Using Object constructors that return objects. How it works?
(2 answers)
What values can a constructor return to avoid returning this?
(6 answers)
What is returned from a constructor?
(7 answers)
Closed 2 years ago.
I've just run into something that really surprises me. Consider the following four functions:
function A() {
this.q = 1;
}
function B() {
this.q = 1;
return this;
}
function C() {
this.q = 1;
return 42;
}
function D() {
this.q = 1;
return {};
}
and let's create objects (via new) from all of them:
console.log('a', new A());
console.log('b', new B());
console.log('c', new C());
console.log('d', new D());
This is the output:
a A { q: 1 }
b B { q: 1 }
c C { q: 1 }
d {}
First three seem to indicate that it doesn't matter what the function returns, that JS only cares about what each function does with this (which was my previous believe, btw). But the last one contradicts that.
So, what's happening here? My revised rule would be "if the function returns an Object, we keep that. Otherwise, we keep this". But I feel quite unsure about it.

in JavaScript when you invoke a function without new like test() it just runs the function and it. returns whatever is being returned by the function
while when you invoke a function with new like new test() it expects the return statement to return an object else return this object.
so
function test() {
this.q = 1
}
test(); // return undefined
new test(); // return {q:1}

When you use the new operator it creates an object.
The return value is as expected. If in the return it is an object will return that object otherwise if the return it is a function will return that function.
function A(){
this.b = 3;
return function(){return 4;};
}
function B(){
this.b = 3;
return { d:4};
}
console.log(typeof (new A())); //function
console.log(typeof (new B())); //object {d:4}
If any other value or non-existent in the return, this operator will take precedence returned as an object.
function C(){
this.b = 3;
return "78";
}
console.log(typeof (new C())); // object {b:3}

Related

What does the This keyword apply to in this Situation

I'm currently working on some exercises to get a deeper understanding of the 'this' keyword. It does seem to have a lot of use cases so I did read on MDN about 'this'. I'm wondering, what does the 'this' keyword in this exercise refer to? I know that when you use apply (which has a maximum of 2 arguments), your first argument is where you want the this 'keyword to be referenced to' and the second argument is an array to which the 'this' keyword is newly referenced to. where is return fn.apply(this,arguments); being referenced to and what is arguments in the second argument? Is it in the function, the window? Sorry, I'm just really confused and trying to wrap my head around it. This is the line of code that I'm confused about:
function add(a, b) {
return a + b;
}
function invokeMax(fn, num) {
var counter = 0;
return function() {
counter++;
if (counter > num) {
return 'Maxed Out!';
}
return fn.apply(this, arguments);
};
}
You can console.log() this in the returned function and find out. Here, you will see it points to the global object (or window in a browser). This code doesn't depend on this being anything in particular. You could rewrite it as:
return fn.apply(null, arguments);
and get the same result.
this is determined by the way functions are called. The function here returns a function that (presumably) you will just call by itself, so the only calling's context is the window:
function add(a, b) {
return a + b;
}
function invokeMax(fn, num) {
var counter = 0;
return function() {
counter++;
if (counter > num) {
return 'Maxed Out!';
}
console.log("this is window?", this === window)
return fn.apply(this, arguments);
};
}
let f = invokeMax(add, 2)
console.log(f(5, 6))
Calling the same function in a different context leads to a different value of this:
function add(a, b) {
return a + b;
}
function invokeMax(fn, num) {
var counter = 0;
return function() {
counter++;
if (counter > num) {
return 'Maxed Out!';
}
console.log("this: ", this)
return fn.apply(this, arguments);
};
}
let someObj = {name: "myObj"}
someObj.f = invokeMax(add, 2) // now this will be someObj
someObj.f()
EDIT based on comment
A basic apply() example. The function will use the object passed to the first parameter of apply() as this in the function:
function print(someArg){
console.log(this.myName, someArg)
}
print.apply({myName: "Mark"}, ["hello"]) // set this to the passed in object
print.apply({myName: "Teddy"}, ["hello"]) // set this to the passed in object
print("hello") // called normally `this` will be the widow which doesn't have a `myName` prop.
// but you can give window that property (but probably shouldn't)
window.myName = "I'm window"
print("hello")
In that instance this refers to the current scope, which is the function where this is contained. In JavaScript, functions are also objects that can have properties assigned to them.

Is it possible to get all defined functions inside other function?

Is it possible inside list to get all available functions - a, b, c without their enumeration and without using window?
(function(){
function a() { return 1; }
function b() { return 2; }
function c() { return 3; }
function list()
{
return [a, b, c];
}
})();
No, it's not possible with functions declared directly in the current scope.
To achieve this, you would have to assign the functions to some property of the scope, i.e.:
(function() {
let funcs = {};
funcs.a = function() {
return 1;
}
...
function list() {
return Object.values(funcs);
}
});
NB: Object.values is ES7, in ES6 use:
return Object.keys(funcs).map(k => funcs[k]);
or in ES2015 or earlier use:
return Object.keys(funcs).map(function(k) { return funcs[k] });
If you haven't even got Object.keys, give up... ;)
I understand where you are trying to get. So perhaps this is the closest thing to what you requested, without using the window name (the same object though):
// define a non-anonymous function in the global scope
// this function contains all the functions you need to enumerate
function non_anon() {
function a() { return 1; }
function b() { return 2; }
function c() { return 3; }
function list() { return [a, b, c]; }
// you need to return your `list` function
// i.e. the one that aggregates all the functions in this scope
return list;
}
// since in here the purpose is to access the global object,
// instead of using the `window` name, you may use `this`
for (var gobj in this) {
// from the global scope print only the objects that matter to you
switch (gobj) {
case 'non_anon':
console.info(gobj, typeof this.gobj);
console.log(
// since you need to execute the function you just found
// together with the function returned by its scope (in order to `list`)
// concatenate its name to a double pair of `()` and...
eval(gobj + '()()') // evil wins
);
break;
}
}

Checking whether toString has been assigned [duplicate]

This question already has answers here:
How do I check if an object has a specific property in JavaScript?
(31 answers)
Closed 7 years ago.
I want a debugging output function to contain a test: if the object has a toString function, use it.
But then, every JavaScript object has a toString function, so what I really want is to check whether it has been assigned toString instead of just inheriting a default one.
What's the best way to do this? It occurs to me maybe you could exploit the fact that the inherited function isn't visible in for-in iteration, though it feels like there ought to be an O(1) solution.
something like
obj.hasOwnProperty('toString')
The result of obj.hasOwnProperty('toString') depends on the way how your toString implementation is created. I did some simple test:
function A() {
}
A.prototype.toString = function(){
console.log("A.toString");
};
function B() {
this.toString = function(){
console.log("B.toString");
}
}
var t = [new A(), new B(), new A()];
for(var i=0; i<t.length; i++) {
var hasOwnToString = t[i].hasOwnProperty("toString");
console.log(hasOwnToString);
if(hasOwnToString) {
t[i].toString();
}
}
Result:
false
true
B.toString
false
For A style it's false, but for B style it's true
You can check to see if the toString function is the same as Object (the object all objects descend from)
function hasUserPrototype(obj) {
return Object.getPrototypeOf(obj).toString !== Object.prototype.toString;
}
See Check if an object has a user defined prototype?
function Foo()
{
}
// toString override added to prototype of Foo class
Foo.prototype.toString = function()
{
return "[object Foo]";
}
var f = new Foo();
function Boo()
{
}
var g = new Boo();
function hasUserPrototype(obj) {
return Object.getPrototypeOf(obj).toString !== Object.prototype.toString;
}
document.write(hasUserPrototype(f)); // true
document.write(hasUserPrototype(g)); // false
var x = {}
if (!(x.hasOwnProperty("toString"))) {
x.toString = function() {
return "I am X"
}
}
x.toString()
// "I am X"

Functions that return a function

I'm stuck with this concept of 'Functions that return functions'. I'm referring the book 'Object Oriented Javascript' by Stoyan Stefanov.
Snippet One:
function a() {
alert("A!");
function b() {
alert("B!");
}
return b();
}
var s = a();
alert("break");
s();
Output:
A!
B!
break
Snippet Two
function a() {
alert('A!');
function b(){
alert('B!');
}
return b;
}
var s = a();
alert('break');
s();
Output:
A!
break
B!
Can someone please tell me the difference between returning b and b() in the above snippets?
Assigning a variable to a function (without the parenthesis) copies the reference to the function. Putting the parenthesis at the end of a function name, calls the function, returning the functions return value.
Demo
function a() {
alert('A');
}
//alerts 'A', returns undefined
function b() {
alert('B');
return a;
}
//alerts 'B', returns function a
function c() {
alert('C');
return a();
}
//alerts 'C', alerts 'A', returns undefined
alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());
In your example, you are also defining functions within a function. Such as:
function d() {
function e() {
alert('E');
}
return e;
}
d()();
//alerts 'E'
The function is still callable. It still exists. This is used in JavaScript all the time. Functions can be passed around just like other values. Consider the following:
function counter() {
var count = 0;
return function() {
alert(count++);
}
}
var count = counter();
count();
count();
count();
The function count can keep the variables that were defined outside of it. This is called a closure. It's also used a lot in JavaScript.
Returning the function name without () returns a reference to the function, which can be assigned as you've done with var s = a(). s now contains a reference to the function b(), and calling s() is functionally equivalent to calling b().
// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;
Calling the function with () in a return statement executes the function, and returns whatever value was returned by the function. It is similar to calling var x = b();, but instead of assigning the return value of b() you are returning it from the calling function a(). If the function b() itself does not return a value, the call returns undefined after whatever other work is done by b().
// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;
return b(); calls the function b(), and returns its result.
return b; returns a reference to the function b, which you can store in a variable to call later.
Returning b is returning a function object. In Javascript, functions are just objects, like any other object. If you find that not helpful, just replace the word "object" with "thing". You can return any object from a function. You can return a true/false value. An integer (1,2,3,4...). You can return a string. You can return a complex object with multiple properties. And you can return a function. a function is just a thing.
In your case, returning b returns the thing, the thing is a callable function. Returning b() returns the value returned by the callable function.
Consider this code:
function b() {
return 42;
}
Using the above definition, return b(); returns the value 42. On the other hand return b; returns a function, that itself returns the value of 42. They are two different things.
When you return b, it is just a reference to function b, but not being executed at this time.
When you return b(), you're executing the function and returning its result.
Try alerting typeof(s) in your examples. Snippet b will give you 'function'. What will snippet a give you?
Imagine the function as a type, like an int. You can return ints in a function.
You can return functions too, they are object of type "function".
Now the syntax problem: because functions returns values, how can you return a function and not it's returning value?
by omitting brackets! Because without brackets, the function won't be executed! So:
return b;
Will return the "function" (imagine it like if you are returning a number), while:
return b();
First executes the function then return the value obtained by executing it, it's a big difference!
Snippet one:
function a() {
alert('A!');
function b(){
alert('B!');
}
return b(); //return nothing here as b not defined a return value
}
var s = a(); //s got nothing assigned as b() and thus a() return nothing.
alert('break');
s(); // s equals nothing so nothing will be executed, JavaScript interpreter will complain
the statement 'b()' means to execute the function named 'b' which shows a dialog box with text 'B!'
the statement 'return b();' means to execute a function named 'b' and then return what function 'b' return. but 'b' returns nothing, then this statement 'return b()' returns nothing either.
If b() return a number, then ‘return b()’ is a number too.
Now ‘s’ is assigned the value of what 'a()' return, which returns 'b()', which is nothing, so 's' is nothing (in JavaScript it’s a thing actually, it's an 'undefined'. So when you ask JavaScript to interpret what data type the 's' is, JavaScript interpreter will tell you 's' is an undefined.) As 's' is an undefined, when you ask JavaScript to execute this statement 's()', you're asking JavaScript to execute a function named as 's', but 's' here is an 'undefined', not a function, so JavaScript will complain, "hey, s is not a function, I don't know how to do with this s", then a "Uncaught TypeError: s is not a function" error message will be shown by JavaScript (tested in Firefox and Chrome)
Snippet Two
function a() {
alert('A!');
function b(){
alert('B!');
}
return b; //return pointer to function b here
}
var s = a(); //s get the value of pointer to b
alert('break');
s(); // b() function is executed
now, function 'a' returning a pointer/alias to a function named 'b'. so when execute 's=a()', 's' will get a value pointing to b, i.e. 's' is an alias of 'b' now, calling 's' equals calling 'b'. i.e. 's' is a function now. Execute 's()' means to run function 'b' (same as executing 'b()'), a dialog box showing 'B!' will appeared (i.e. running the 'alert('B!'); statement in the function 'b')
Create a variable:
var thing1 = undefined;
Declare a Function:
function something1 () {
return "Hi there, I'm number 1!";
}
Alert the value of thing1 (our first variable):
alert(thing1); // Outputs: "undefined".
Now, if we wanted thing1 to be a reference to the function something1, meaning it would be the same thing as our created function, we would do:
thing1 = something1;
However, if we wanted the return value of the function then we must assign it the return value of the executed function. You execute the function by using parenthesis:
thing1 = something1(); // Value of thing1: "Hi there, I'm number 1!"
Here is a nice example to show how its work in practice:
when you call in with two parameter and returns a result
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
console.log(sum(3)(8))
there is also another way using the accessing to the arguments in js:
function sum(x) {
if (arguments.length == 2) {
return arguments[0] + arguments[1];
} else {
return function(y) { return x + y; };
}
}
Let's try to understand the "return" concept with two examples with the same output, one without using the "return" concept and the other with the "return" concept, both giving the same outcome.
let myLuckyNumber = 22
function addsToMyLuckyNumber(incrementBy, multiplyBy) {
myLuckyNumber = (myLuckyNumber + incrementBy) * multiplyBy
}
addsToMyLuckyNumber(5, 2)
console.log(myLuckyNumber)
const myLuckyNumber = 22
function addsToMyLuckyNumber(incrementBy, multiplyBy) {
return (myLuckyNumber + incrementBy) * multiplyBy
}
myNewLuckyNumber = addsToMyLuckyNumber(5,2)
console.log(myLuckyNumber, myNewLuckyNumber)
In the first snippet, you can see the code
myLuckyNumber = (myLuckyNumber + incrementBy) * multiplyBy
you cannot assign a similar code to the second snippet, since it will not work, so we use "return" concept and assign a new variable.
function addsToMyLuckyNumber(incrementBy, multiplyBy) {
return (myLuckyNumber + incrementBy) * multiplyBy
}
myNewLuckyNumber = addsToMyLuckyNumber(5,2)

how to use function(1)(2) in javascript? and how does it work?

I understand calling function(1) but not function(1)(2), how does it work?
also possible for function(1)(2)(3)(4) too?
In this case you are supposing that function(1) returns a function, than you are calling this new, anonymous function with an argument of 2.
See this example:
function sum(a) {
return function(b) {
return a+b;
}
}
// Usage:
window.alert(sum(5)(3)); // shows 8
var add2 = sum(2);
window.alert(add2(5)); // shows 7
window.alert(typeof(add2)); // shows 'function'
Here we create a function sum that takes one argument. Inside the function sum, we create an anonymous function that takes another argument. This anonymous function is returned as the result of executing sum.
Note that this anonymous function is a great example of what we call closure. A closure is a function that keeps the context in which it was created. In this case, it will keep the value of the variable a inside it, as did the example function add2. If we create many closures, they are independent as you can see:
var add3 = sum(3);
var add4 = sum(4);
window.alert(add3(3)); // shows 6
window.alert(add4(3)); // shows 7
Furthermore, they won't get "confused" if you have similarly named local variables:
var a = "Hello, world";
function multiply(a) {
return function(b) {
return a * b;
}
}
window.alert(multiply(6)(7)); // shows 42
var twoTimes = multiply(2);
window.alert(typeof(twoTimes));
window.alert(twoTimes(5));
So, after a call to sum(2) or multiply(2) the result is not a number, nor a string, but is a function. This is a characteristic of functional languages -- languages in which functions can be passed as parameters and returned as results of other functions.
You have a function that returns a function:
function f(n) {
return function(x) {
return n + x;
};
}
When you call f(1) you get a reference to a function back. You can either store the reference in a variable and call it:
var fx = f(1);
var result = fx(2);
Or you can call it directly:
var result = f(1)(2);
To get a function that returns a function that returns a function that returns a function, you just have to repeat the process:
function f(n) {
return function(x) {
return function(y) {
return function(z) {
return n + x + y + z;
}
}
};
}
If your function returns a function, you can call that too.
x = f(1)(2)
is equivalent to:
f2 = f(1)
x = f2(2)
The parenthesis indicate invocation of a function (you "call" it). If you have
<anything>()
It means that the value of anything is a callable value. Imagine the following function:
function add(n1) {
return function add_second(n2) {
return n1+n2
}
}
You can then invoke it as add(1)(2) which would equal 3. You can naturally extend this as much as you want.

Categories