Javascript - Function Being Executed Immediately when Stored as Variable? - javascript

First post. New to programming.
In Javascript, when I declare a new variable and also set this newly declared variable to store a function, is that function immediately executed when the code runs (execution context)?
For instance,
function Person() {
console.log(this);
this.firstname = 'John';
this.lastname = 'Doe';
}
var john = new Person();
Is the variable john being declared at the same time the function "Person" is being executed on that same line?

What you copy/paste is an object creation. It means john is a new Person object. Person being the class of the object. The this keywork in your Person function is related to the instance of the newly created object. Don't be abused by the function keyword, which is a confusing (because of historical reason) JS keyword. Person function can be seen as an object constructor.
EDIT : removed the off topic remark (really too much off topic)

var john = new Person();
Variable john is created.
RHS is executed.
2.1. new operator calls the contructor of the Person. Every function implictly has a constructor(). This results in Object creation.
Result of RHS evaluation is returned (which is an object in this case).
Result is assigned to john or in other words, now john (a reference variable) will refer to the object which was created as a result of new operator executed on Person().

If you put () or (optionalArgumentsHere) (some functions take arguments, some don't) after a function it means it is a function call, and it will be executed. If you want to assign the function itself to a variable, you need to omit the (). It is possible because functions are objects in JavaScript (which is not true in every language).
So what happens here is that you declare a variable (you actually declare it earlier because of hoisting, as explained by Pablo), you execute new Person() and assign the result to the variable.
If you called some function like
function fun() {
return 5;
}
var x = fun();
You would be assigning the return value of the function to the variable. But your case is special, because you use new. That means Person is a constructor, and it is used to create a new object of type Person. Inside that constructor, you use the this keyword to attach properties to the newly created object. The new Person() call returns the object, even though return is not called explicitly.

In Javascript, variable definitions are "hoisted". It means that the code that you posted and the following one...
var john;
function Person() {
console.log(this);
this.firstname = 'John';
this.lastname = 'Doe';
}
john = new Person();
... are identical, because the compiler will hoist the variable declaration to the beginning of the current context. So, the answer is no, the variable is declared, then the function is executed as a constructor, and then the new creadted object is assigned to that variable.
You can find more information here

Related

Using This in Javascript

I have read over some rules to determine what the value of this is in different scenarios in Javascript. All was well till the example below threw me off.
function Person(name){
this.name = name; //this is the object when function used as constructor (as expected)
this.changeName = someFunction(); // produces error
function someFunction(){
this.nickName = this.name+"by"; //this is now the global object and not the instance, thus the name property does not exist.
}
}
var a = new Person ('bob'); //error due to the function in changeName property.
From what I understood, the this variable takes up the value of the invoking object when called through dot notation or takes up the value of the newly constructed function when used with the new key word.
Can someone explain why the this statement in the function above is the global objet and not the newly instantiated object?
Can someone explain why the this statement in the function above is the global objet and not the newly instantiated object?
Because when you call a(n unbound) function as func(), this will refer to the global object (or undefined if the function is in strict mode).
Every function (except arrow functions) has its own this value. So the fact that you are calling Person as new Person() and that this inside Person refers to a new object, doesn't have any impact on the this value in someFunction. It only matters how you can someFunction.
You could call someFunction and explicitly set its this value via .call:
this.changeName = someFunction.call(this);
See also: How to access the correct `this` inside a callback?
The this within someFunction() will reference a global object, because it's inside a function call. See a fuller, much more complete explanation at How does "this" keyword work within a function?
If you wish to solve the issue, alias this inside the parent.
function Person(name){
var self = this; // Store a reference to the current instance
self.name = name;
self.changeName = someFunction(); // Odd that you'd capture the return value of a setter, ...
function someFunction(){
self.nickName = self.name+"by"; //self references the instance, creating the property.
}
}

If a variable is enclosed, and an instance sets a property with the same name, where does the property go?

Most of us know that JavaScript has no sense of "private" properties, but that behavior can be emulated through the use of closures:
var Car = function () {
var name = 'Tesla';
var wheelCount = 4;
this.getName = function () {
return name;
};
this.getWheelCount = function () {
return wheelCount;
};
this.setName = function (newName) {
name = newName;
};
this.setWheelCount = function (newCount) {
wheelCount = newCount;
};
};
var myCar = new Car();
console.log(myCar.name); // undefined
That all makes sense to us that know about how JavaScript closures work. However, the following will work:
myCar.name = 'Corvette';
console.log(myCar.name); // 'Corvette'
But then if you call the function from the prototype, the enclosed variable is still used
console.log(myCar.getName()); // 'Tesla'
When you call myCar.name, you're adding a new property to the object. Is it just the entire point of using this when declaring the getName (etc) functions inside the Car definition to make the differentiation between the enclosed name inside the Car declaration versus the myCar.name?
I have a feeling that I know the answer to this, but I would like to be certain. Plus, I think this would be something invaluable to other people getting an advanced grasp on how JavaScript enclosures work.
Is it just the entire point of using this when declaring the getName (etc) functions inside the Car definition to make the differentiation between the enclosed name inside the Car declaration versus the myCar.name?
Yes.
this (or myCar) is the object, on which you put the properties that you want to have it (in this case all those methods). If you want to use properties, you must use a property accessor.
var name is just a local variable in the constructor function, which is accessed by closure from the object's methods.
Or, to answer your title question:
If a variable is enclosed, and an instance sets a property with the same name, where does the property go?
The property goes on the object. It doesn't interfere at all with the variable, which is located in the scope of the Car constructor invocation.
In your example car function is a constructor function. When a constructor function is called with new operator, a new object is created and "this" gets bound to that new object. And "this" is returned from the function even if there is no return statement (unlike non-constructor functions that returns undefined if nothing is returned)
So When you called new Car() a new object got created and as "this" was bounded to this new object, the new object got 4 functions that you defined in Car function (getName, getWheelCount, setName, setWheelCount)
The name variable defined in Car function is not bounded to "this", it is bounded to Car's function scope. When car function returned "this", because of closure getName() still has access to function's name variable.
Now when you tried myCar.name, as the new object that was created does not have any variable called name, it printed undefined.
On doing myCar.name = 'Corvette', as no property named name was found in myCar,new property was created with name "name" and value "Corvette" (javascript creates a new property if it is not already existing in case of write operations, for read operations prototype chain is followed)
But surprisingly myCar.getName() still prints "Tesla" and not Corvette, because though the variable names are same they are in diffrent scope.The one that is referred by getName was part of Car function scope and is bounded to getName via Closure, but the name ("corvette") that you added belongs to new object that you created.
The purpose of "this" is to add the functions/variables defined inside constructor function to the object that you are going to create through that constructor function.
Hope it helps.

Why would you set the JavaScript prototype to an anonymous function?

In this article
The prototype object is being set to the "superclass"
function Mammal(name){
this.name=name;
this.offspring=[];
}
Cat.prototype = new Mammal();
In the code that I am reading right now, it has this construct
COMPANY.BILLING = function(){
//more code
}
COMPANY.BILLING.prototype = (function(COMPANY){
//more code
})(COMPANY)
I am confused, why would you set the value of the prototype object to an anonymous function? This is not some sort of inheritance, right?
Is this some sort of a JavaScript pattern?
Careful, the prototype is not set to an anonymous function there, but to it's return value:
COMPANY.BILLING.prototype = (function(COMPANY){
//more code
})(COMPANY);
^^^^^^^^^ -> the function is called immediately
This means that the prototype is assigned the self-calling function's return value, whatever that might be:
COMPANY.BILLING.prototype = (function(COMPANY){
return new Foo(); // the new Foo will be assigned to the prototype
})(COMPANY);
Usually, these self-calling functions are wrapped around chunks of code to avoid polluting a scope with symbol names, preventing duplicate symbol names and, last but not least, preventing confusion about the purpose of a variable (JavaScript only has functional scoping, at least current versions do). Any variable/function name declared in a function body is visible in the containing function body, but not outside:
var sampleVariable; // this is visible across this example
COMPANY.BILLING.prototype = (function(COMPANY){
var yetAnotherVariable; // this is only visible "inside" the self-calling function
return new Foo(); // the new Foo will be assigned to the prototype
})(COMPANY);

Javascript scope/this

How come when I do:
function Dog(){
this.firstName = 'scrappy';
}
Dog.firstName is undefined?
However then I can do:
Dog.firstName = 'scrappy';
And now Dog.firstName returns 'scrappy'?
How come when I do ... Dog.firstName is undefined?
Because...
... Dog is never called, so the line this.firstName = 'scrappy'; is never executed and ...
... even if you call the function, this probably won't refer to the function Dog. You can call it in a way that this refers to Dog, but that is rather unusual . How the value of this is determined has been explained extensively.
However then I can do ... And now Dog.firstName returns 'scrappy'?
Functions are just objects, so you can assign any property to it.
The Dog() function is just the constructor, so you're calling firstname on the constructor rather than an instance of it. This isn't defined just by virtue of it being defined on the returned objects, they're totally separate things. However, because you can augment functions with fields, you were able to assign a value to dog.firstName anyway.
First, let me demonstrate the difference between a constructor and an instance:
function Dog() {
this.firstName = 'scrappy';
}
Dog.firstname; // undefined on the constructor
Dog.prototype; // defined on constructor, returns an empty object
var myDog = new Dog();
myDog.firstname; // defined on instance, returns 'scrappy'
myDog.prototype; // undefined on instance
As you can see, a constructor (a function that returns an object) is a totally different thing to the object it returns, and has totally different fields as a result. What you were seeing when you got Dog.firstname to return 'scrappy' was the result of adding a new field to the constructor. This is doable, but remember, adding a field to the constructor will not add the same field to the constructed. Consider:
Dog.someNewProperty = 'whatever';
var myDog = new Dog();
Dog.someNewProperty; // 'whatever'
myDog.someNewProperty; // undefined

JavaScript function binding (this keyword) is lost after assignment

this is one of most mystery feature in JavaScript, after assigning the object method to other variable, the binding (this keyword) is lost
var john = {
name: 'John',
greet: function(person) {
alert("Hi " + person + ", my name is " + this.name);
}
};
john.greet("Mark"); // Hi Mark, my name is John
var fx = john.greet;
fx("Mark"); // Hi Mark, my name is
my question is:
1) what is happening behind the assignment? var fx = john.greet;
is this copy by value or copy by reference?
fx and john.greet point to two diferent function, right?
2) since fx is a global method, the scope chain contains only global object. what is the value of this property in Variable object?
john.greet("Mark") actually calls a function. When you do var fx = john.greet;, you're getting a reference to the function. So when you call it, this is not bound to john. What you're actually doing is window.fx("Mark") and so this is the window object. You were on the right track when you said that it was in the global context. In this particular instance, the global object is window, and so fx is actually window.fx.
When you have a function reference you should use call or apply if you want to set the value of this. Try doing this:
fx.call(john, "Mark");
The first argument in call or apply is the value used for this in the context of the function call.
EDIT
Some people mentioned that the real issue here might be confusion surrounding an object literal vs. an instance of an object. You're creating an object literal which also behaves kind of like a singleton. You cannot create a new instance of that object. In this case john is a reference to that object literal. In that context, this in the function greet refers to the object literal itself. Hence when you call john.greet("Mark"), this is bound to john.
When you grab a reference to john.greet just by itself and assigning it to a global variable, you're essentially doing this:
var fx = function(person) {
alert("Hi " + person + ", my name is " + this.name);
}
In this scenario, this is window, because fx is basically window.fx (since the global object here is window. Assuming this code was wrapped inside another function, then the global object would refer to that function.
If you want to create multiple instances of an object, you can do something like this:
var Person = function(name) {
var self = this; //maintains a reference to the instance
this.name = name;
this.greet = function(name) {
alert("Hi " + name + ", my name is " + self.name);
}
}
var john = new Person("John");
john.greet("Mark"); // alerts "Hi Mark, my name is John"
var fx = john.greet;
fx("Mark"); // also alerts "Hi Mark, my name is John"
Here, the self variable (which is local to the function) maintains a reference to the actual instance because you're binding it to this when you create the object.
There are many best practices associated with OOP in Javascript. You can Google and find out (there are many links). I recommend reading stuff from Douglas Crockford especially.
1) fx and john.greet are referring to the same function object, the assignment operation for objects, works by reference.
For primitive values, like String, Number, Boolean undefined or null, a copy of the value will be made.
2) The this value refers to the global object.
The this value is not a property of the Variable Object and it has nothing to do with the scope chain, is a special reserved word, and it is determined implicitly when a function is called (you can also set it explicitly via call or apply).
JavaScript internally handles a Reference type, which consists of two components, the base object and the property name, when a function is invoked, the this value is determined implicitly by getting the base object (by the internal GetValue operation).
And finally, the last case where this is set implicitly is when you invoke a function with the new operator, the this keyword will refer to a newly created object.
So in brief, here is how this works implicitly:
1- When a function is called as a method (the function is invoked as member of an object):
obj.method(); // 'this' inside method will refer to obj
2- A normal function call:
myFunction(); // 'this' inside the function will refer to the Global object
// or
(function () {})();
3- When the new operator is used:
var obj = new MyObj(); // 'this' will refer to a newly created object.
As I understand it, you're only assigning that method to the variable "fx." The context of the john object doesn't come along with it.
Off the top of my head, "this" in the context of fx will refer to the global object, which in the context of a browser is (I believe) equivalent to your window object.
(editing to clarify global object. Sort of)
Because you're only setting fx to the greet method and not the entire john object, it has no concept of it's parent and becomes globally scoped. So in essence, it's passing by value in that in only copies the method.
Since the function is now globally scoped, "this" becomes the Window object.
If you instead set fx to john, you get what's expected.
var john = {
name: 'John',
greet: function(person) {
alert("Hi " + person + ", my name is " + this.name);
}
};
john.greet("Mark"); // Hi Mark, my name is John
var fx = john;
fx.greet("Mark"); // Hi Mark, my name is John
inspired by #Vivin Paliath answer, actually I come out something new. As to me, I always try my best to make javascript programming the same way as java, especially in OOP.
So my suggestion is to avoid using this as possible as we can , when we first do
var self = this;
we should use self instead of this in all function (prototype function, whatsoever), but if we write something like this:
function MyObject = {
var self = this;
};
MyObject.prototype = {
method1 = function(data){
self.data = data;
}
}
This is not gonna work, because prototype is an object in MyObject, It can not access private member self owned by MyObject. My solution for this is simple:
function MyObject = {
var self = this;
MyObject.prototype.method1 = function(data){
self.data = data;
};
}
This takes the advantage of prototype's efficiency and also we do not have to care about all the this issues. Though we gonna type a lot of MyObject.prototype.xxxx thing.
If this helpful to your guys, please give me some thumb up, so I can gather 15 reputation to thumb up others, thanks.

Categories