Understanding execution of properties in Javascript funciton - javascript

i am starting to learn javascript and i got confused on the execution of the properties in the javascript function.
suppose i have a funciton like this
function Counter() {
this.num = 0;
this.timer = console.log('hey');
};
now in this function, i have num and timer as a properties of the function Counter. when i try to make a instance of the function Constructor the timer property gets executed
but when i try to call the timer property explicitly, i am not getting the value / the property is not getting executed.
what is the reason behind it?

now in this function, i have num and timer as a properties of the function Counter.
No, you have num and timer properties of objects created by calling Counter as a constructor (via new, or Reflect.construct, etc.).
but when i try to call the timer property explicitly, i am not getting the value / the property is not getting executed
Just briefly on terminology (since this will help as you continue your learning), you don't "call" properties, and properties are not "executed." You "get" their value, or "access" them, or "read" them. (Or, when they're on the left-hand side of an assignment, you "set" them or "assign to" them or "write to" them.)
Your code is successfully getting the value of the timer property, which is the value that console.log('hey') returned, which is undefined.
If you meant for doing something with timer to make it run the console.log, you'd want to put it in a function:
this.timer = function() {
console.log('hey');
};
and then call it (because you do "call" functions):
d.timer();
Side note:
If that's what you meant to do, while it's perfectly fine to create functions within the constructor like that, it's slightly more common to assign them to the prototype object that new Counter will give to the objects it creates. With ES5 and earlier, you'd do that like this:
function Counter() {
this.num = 0;
} // <== No ; here, it's a declaration, not a statement
Counter.prototype.timer = function() {
console.log('hey');
};
In ES2015+, you'd probably use class syntax instead:
class Counter() {
constructor() {
this.num = 0;
}
timer() {
console.log('hey');
};
}
You use them the same way (via new).

It is quite easy.
this.timer = console.log('hey');
This line assigns to the property timer the return value of console.log('hey').
console.log prints in the console, but does not return anything, so your property stays undefined.
You are confused because you mix what is printed in the console and the actual return value.
If you just run in the console the following: console.log('hey'), you will see the following: hey then undefined. What the console.log function prints, then its return value.

On creating a new object using Counter as a constructor, a new object is created with 2 properties i.e. num and timer. num is initialized to 0 while timer is initialized with the return value of console.log() function which is undefined. This return value is stored as value of timer property and each time you get this while reading it.
If I understand correctly, you wants to add some functionality to the timer property as a function, you can do it by adding this to the prototype property of Counter so that all objects created using a constructor can inherit it.
function Counter() {
this.num = 0;
};
Counter.prototype.timer = function() {
this.timer = console.log('hey');
}
let obj = new Counter();
obj.timer();

Related

redefine function definition in javascript without reassigning it

Functions are callable objects in javascript so is it possible to redefine a function definition
?
so basically what I am trying to do is:
let a = function(){console.log('first');}
let b = a;
/**
* alter definition of function 'a' something like:
a.redefine(function(){console.log('second');});
*/
b();//should log 'second'
I looked up for javascript function documentation here as well as here but couldn't find any reference on how/where functions definition are actually stored, even tried to inspect a.prototype as well as altering a.prototype.constructor but got nothing.
A workaround on this can be something like:
let functionHolder={
a:function(){console.log('first');}
}
let a = function(){functionHolder.a();}
let b = a;
functionHolder.a=function(){console.log('second');}
b();//would log 'second'
however my ultimate goal is to understand how functions actually work/stored in js and not a workaround just to achieve this.
It's not possible. Once a function has been defined, its "function code" is immutable. The only way for a variable name which references a function to reference different "function code" would be to reassign the variable name to a new function.
Your
functionHolder.a=function(){console.log('second');}
is essentially the same thing - you're reassigning the function that functionHolder.a refers to.
In the specification, when you call a function, you invoke its internal method [[Call]], which eventually leads you to
OrdinaryCallEvaluateBody, which does:
Return the result of EvaluateBody of the parsed code that is F.[[ECMAScriptCode]] passing F and argumentsList as the arguments.
And the ECMAScriptCode internal property is not reassignable - it's only set in FunctionInitialize, when a new function is created (like when you do
<someIdentifier> = function(){console.log('second');}
)
It is possible by turning the b variable into a getter on the window object.
It's not pretty, but it works:
let a = () => "foo";
console.log("a", a());
Object.defineProperty(window, 'b', {
get() { return a; }
});
console.log("b", b());
a = () => "bar";
console.log("b", b());
a is a reference to a function. Call it a "pointer".
b is a copy of that pointer.
When you re-assign a, you're replacing the pointer. If another variable still points to the value behind the old pointer, that value still exists. That's why in your example, b didn't change: b was a pointer to the old function.
That getter is basically a function that's executed without explicitly having to call it, so it always gets the latest result of whatever the getter function does.

What is it called when a function behaves like a class but doesn't use the class keyword, nor "new" keyword (in Javascript)?

I looked through the suggested links but can't seem to find the term for a function that acts like a class (is it a constructor function? doesn't have that keyword either!) but doesn't use the new keyword, nor class.
I've used both this example's pattern and the class pattern in my code but realized I don't know how to describe the former.
I think this is in part because I learned JS recently, have seen class thrown around a lot, yet looking through my notes of not-ES5,6,7,2018,2020 etc. can't seem to find what var aCounter = counterFunction() is called for the life of me.
I know what the result of what i'm doing is, how to work it, etc. but why no constructor(), no new, no class, no etc.prototype.etc pattern? I know i'm creating an object, calling a method existing Within the object, etc. I believe i'm beginning to ramble.
Lo, an example
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
which is || can be instantiated (?) like so:
let aCounter = counterFunction() // where i'm getting tripped up
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
I know this is rambling, but help! I think it will make things click more inside once this lexical puzzle piece is put into position!
That is just a function that returns an object literal, which does not act like a class (doesn't have a prototype, and as you pointed out, does not use new, etc).
The functions that are set as the properties of this object (which you store in aCounter) seem to act like class methods because they keep the reference to the variable val alive, but this is not because val is in any way associated with the actual object.
Instead, those functions are closures that keep the reference to the variable alive for as long as the functions themselves are alive.
So to answer your question, what you have described doesn't have any name in particular. It's just a function that returns an object.
Edit:
You asked why there is no constructor() or related syntax in this pattern. Object literals in JavaScript are just mappings of names and values:
const x = { a: 3, b: "hello" };
You do not need a constructor for this, and there is no prototype because it was not instantiated using a constructor. On the other hand, classes and constructor functions are templates for objects that will be created later, and those objects do have a prototype and a constructor because the template contains logic that initializes the object.
class A
{
constructor()
{
this.a = new Date();
this.b = this.a.toString(); // you cannot do this in an object literal
}
}
const x = new A();
Question:
What is it called when a function behaves like a class but doesn't use the class keyword, nor “new” keyword (in Javascript)?
Answer:
It's called a "factory function".
Factory functions usually return a object of a consistent type but are not instances of the factory function itself. Returned objects would rarely inherit from the factory function's prototype property, and calling the factory function does not require new before the function being called.
What you showed there is nothing special. It is just a normal function that has a closure.
Though, you can call it as a type of design pattern.
It looks similar to Revealing Module Pattern where you can separate public property and private property.
Below is an example (not a good one tho):
var counter = function(){
var privateCount = 0;
var privateHistory = [];
return {
getVal: function(){
return privateCount;
},
increment: function(){
privateCount++;
privateHistory.push('+');
return this.getVal();
},
decrement: function(){
privateCount--;
privateHistory.push('-');
return this.getVal();
},
publicHistory: function(){
return privateHistory;
}
}
}
var aCounter = counter();
console.log(aCounter.increment());
console.log(aCounter.decrement());
console.log(aCounter.publicHistory());
Here, you can't directly manipulate the private variables that I don't expose to you.
You can only manipulate those private variables only if I expose the function to you. In this case, the .increment() and .decrement() function.
As you can see, there is no class, no prototype, no constructor.
I can see how you may get tripped up, let's go through your code and explore what's going on:
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
At this point counterFunction is a variable that points to a function, it's essentially a function name. The ()=>{...} is the function body or function definition and within it the return statement shows that it returns an unnamed object with two property methods.
let aCounter = counterFunction() // where i'm getting tripped up
This is calling your previously defined function, which again returns the object with two methods and assigns it to the variable aCounter. If you did the same thing again for a variable called bCounter they would hold two independent objects.
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
Because the method inside the object refers to a variable outside the scope of the object, but within the function body, a closure is created so that the state of val may be retained. Because the variable is in use, the browser's cleanup process skips over it, so the function is still kept in memory, I believe until the object is destroyed and the function's variable is no longer used.

Why cannot use function name to retrieve property in JavaScript?

The following is the code
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
console.log(add.num); //outputs :undefined
Function name can be treated as reference of a function object, so the num is the property of add function object, the outputs could have been 0. But the result is not like so, why?
If i change the code to:
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
var obj = new add();
console.log(obj.num); //outputs : 0
it works correctly. Can anyone explain this? Many many many thanks.
this refers to current instance of your function. until you create a new instance using new add() this will refer to window object.
add.num will check if add has a property named num. Which is false because add refers to a function definition not an instance/object of function.
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
console.log(add.num); //outputs :undefined because add=function(){};
while in another case, when you create object using new it returns you a javascript object having all the public properties.
///obj=Object{ num : 0};
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
var obj = new add();
console.log(obj.num); //outputs : 0 because obj is {num:0}
Fiddle to play: http://jsfiddle.net/ZpVt9/76/
It will help to read-up on this in JavaScript: MDN
When you do new add(), the interpreter creates a new JavaScript Object/Hash and binds it to this variable in the function. So this is valid inside the scope of the function.
When you don't do a new you are calling the function without a context, so this is undefined in such cases (in 'use strict' mode).
You can explicitly pass a context to Functions using Function.apply/Function.call/Function.bind
this inside a function points to different object depending on how the function is called:
If the function is called in the global context (outside any function) this points to global object (which is window if the script is executed within a browser).
console.log(this === window) will output true.
If this is referred inside a function, then it depends if we have set strict mode.
If the code is in strict mode then this will be undefined unless we explicitly assign it to something.
If the code is not in strict mode then this will point to global object. (Which is again window if script is executed in a browser).
If function is used as constructor to make new objects then this points to the new object being made.
If function is used as object method then this points to the object method is called on.
More explanation with examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Every function is an object in JavaScript. But as you can see from above explanation none of the ways this points to function object itself from the same function body. Thus the only way you can set function's property is by directly assigning it to the function without using this.
There is another way of adding a property to functions. This is a very bad idea of doing so as adding any property this way will reflect in all functions used. Every function is linked to Function.prototype object. Thus adding any property in this object will get reflected in all functions.
Function.prototype.someProperty = 1;
//now try accessing it via any function object
console.log(add.someProperty); //should print 1 to console.
"num" is not a property of the "add" function is a property of the object created and returned by that function if you want to add num to your add function you need to do
add.prototype.num=0;
and remove it from your objects definition

Do, inner and outer functions get their own copy of same variable?

just a bit confused by this code
var counter = function() {
//...
var count = 0;
return function () {
return count = count + 1;
}
}
var nextValue = counter();
console.log(nextValue());
nextValue.count = 7;
console.log(nextValue());
console.log(nextValue.count);
console.log(nextValue());
Output is
1
2
7
3
It's counter intuitive. There are two representations of count. One on the outerfunction nextValue and one that only the inner anonymous function can see.
Correct, or are my missing something?
The expression nextValue.count does not refer to the local variable "count" declared inside the function. It is not possible, in fact, to create a reference to a variable local to a function from code outside the function. What you're referencing there is simply a property of the function object.
So, yes, the "count" variable that the returned function has access to is effectively completely private to that function, and it is persisted in the closure formed by the call to the "counter" function.
If you did want that to work, you could do this:
function counter() {
function actual() {
return actual.count = actual.count + 1;
}
actual.count = 0;
return actual;
}
edit — (fixed bogus code) the name "actual" inside gives the returned function safe access to the function object itself; originally I typed "this" there, and that would not work unless the external code set it up explicitly.
The way you describe it, count is effectively a private variable. When you're assign to nextValue.count, you're creating a separate property--not accessing the internal count being incremented by your counter.

javascript function object method

Hey im new to javascript and i stumbled upon this code in javascript. I dont understand how can be methods increment and print defined inside function. Does that mean that create is an object?
function create() {
var counter = 0;
return {
increment: function () {
counter++;
},
print: function () {
console.log(counter);
}
}
}
var c = create();
c.increment();
c.print(); // 1
The function "create()" returns an object. The object it returns has two properties, "increment" and "decrement", both of which have functions as values. The functions operate on the variable "counter" defined in "create()".
Each call to "create()" instantiates a new context called a "closure". The context encloses a new copy of the "counter" variable. The objects returned from calls to "create()" thus have access to their own private "counter" instance.
The keyword for you is closure.
Closures in javascript are quite covered, e.g. in How do JavaScript closures work?.

Categories

Resources