javascript function object and this - javascript

What's difference of this in the following two cases?
Case 1
var Person = function() { this.name="Allen Kim" }
Person.name; //undefined
Case 2
var Person = function() { this.name="Allen Kim" }
var me = new Person();
me.name // Allen Kim
Just wanted to understand how this scope works on both cases.

Every function in JavaScript is itself an object. So Person.name retrieves the name property from the function itself, which was never set; hence undefined.
You can try this my setting it directly:
Person.name = "John";
Person.name; // "John"
When assigning a property from within the constructor via
this.name = "Allen Kim";
you're setting the property on that instance. When you then instantiate an object with:
var me = new Person();
your constructor will add the name property to me, since this referes to the object being created.
Here are the basic steps taken by the JavaScript engine when calling a constructor function with the new keyword:
Calls the constructor with this set to a new clean object.
Sets the internal [[Prototype]] property of your new object to the constructor's prototype (which, in some implementations, is then available through __proto__).
Sets up the constructor property of your new object as a reference to the constructor function (so instead of the non-standard me.__proto__, you could access the prototype via me.constructor.prototype).
Returns said object.
Note that this is a very basic explanation. There are many other things not included here, but this should give you the gist of it.

On the first case you are looking for a static property on the function itself.
The second case you are returning an instance of an object that has the property by calling a constructor function. Its not really a matter of scope.

var Person = function() { this.name="Allen Kim" }
Person.name; //undefined due to the fact that there is no Person object.
var Person = function() { this.name="Allen Kim" }
var me = new Person();
me.name // Allen Kim --> Person `me`'s name

Related

Why is old constructor for function called?

It is my understanding that when you change the function prototype of a function to point to a different object the constructor of the new prototype will point to the new object's prototype constructor.
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new:
When the code new Foo(...) is executed, the following things happen:
1) A new object is created, inheriting from Foo.prototype.
2) The constructor function Foo is called with the specified arguments,
and with this bound to the newly created object. new Foo is equivalent
to new Foo(), i.e. if no argument list is specified, Foo is called
without arguments.
3) 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.)
Furthermore, from https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance:
We need to do one more thing before we move on. After adding the last
line, Teacher.prototype's constructor property is now equal to
Person(), because we just set Teacher.prototype to reference an object
that inherits its properties from Person.prototype! Try saving your
code, loading the page in a browser, and entering
Teacher.prototype.constructor into the console to verify.
In my example below customPrototype inherits its properties from Object.prototype as far as I can tell and so once I reassign Person.prototype to that it should change the constructor as well. And logging it I see that the constructor does change!
// Some custom object to inherit
var customPrototype = {
name: "XYZ"
};
// Person has its prototype object pointing to Object.prototype
var Person = function() {
this.name = "Not XYZ";
};
// Prints function() {this.name = "Not XYZ";}
console.log(Person.prototype.constructor);
// Change Person prototype to point to the custom prototype object
Person.prototype = customPrototype;
// Prints function Object() { [native code] }
console.log(Person.prototype.constructor);
var p = new Person();
// Prints Not XYZ
console.log(p.name);
Given the example above I expected the last name to print XYZ because nothing would be overwritten from the customPrototype object.
What am I missing? Why does it still call the Person function when (I think) it should be calling the Object.prototype.constructor?
Prototype.constructor have nothing to do with object initialization. When you want to create an object, you call new Person(), which actually calls the Person function, passes the object as the context (this) into the function and returns that object. Person function is called, no matter what prototype you have for it. And because in this function you have a property name set to Not XYZ, it will have that value. It shadows the prototype property with the same name. If you will delete this property from the object and try to again access name, you will get the prototypes one.
var customPrototype = {
name: "XYZ"
};
var Person = function() {
this.name = "Not XYZ";
};
Person.prototype = customPrototype;
var p = new Person();
console.log(p.name);
delete p.name;
console.log(p.name);
We set the prototype.constructor to keep the precise construction of the object and if we want to have some checkings based on which type of the object is.
Implementing copy logic for the objects of the type Person.
function Person(name) {
this.name = name;
};
Person.prototype.copy = function() {
return new this.constructor(this.name); // Access by `constructor` property, it is not necessary to call directly `Person`
}
const person = new Person('Bob');
console.log(person.name);
const secondPerson = person.copy();
console.log(secondPerson.name);
console.log(person === secondPerson);

Omitting prototype.constructor changes prototype chain

I'm trying to understand inheritance in JavaScript and I've seen that in JavaScript there are different ways to accomplish inheritance. One such way is based off of an example from the Mozilla site which does something similar to the code below:
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.setName = function(name) {
this.name = name;
}
function Employee(name, Id) {
Person.call(this, name);
this.Id = Id;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.getId = function() {
return this.Id;
}
Employee.prototype.setId = function(Id) {
this.Id = Id;
}
var andrew = new Employee("Andrew", "123");
I understand that this code is pretty basic and that I don't really need to define getters and setters. I only added them to show that I can add to each of the prototype objects. For the most part I understand what this code does.
Where I start to get confused is when I see the following line:
Employee.prototype.constructor = Employee;
I understand that we are setting the constructor property of the Employee.prototype object to point to the Employee constructor function. I have read other posts from this site that say I can omit this line and indeed if I do, everything works as expected. But... When I do omit this line I see some changes to the prototype chain. The __proto__ property of the Employee object now points to a generic Object with the following methods: getId and setId. The __proto__ property of this object then points to the Person.prototype object.
So my question is:
why is it that when I omit Employee.prototype.constructor = Employee that the __proto__ property points to an generic object with the methods I set in the Employee.prototype object and not the Employee.prototype object itself? Further more, how are the getId and setId methods attached to this mysterious prototype and is there any performance hit because of this?
I have attached the console.logs from the Chrome console to show the __proto__ property when manually setting the constructor property and then when omitting it.
Objects don't have names. So what you see next to __proto__ is a name that the console infers somehow. Apparently that way involves constructor somehow.
The prototype chain doesn't change, only the information that is presented to you. __proto__ refers to Employee.prototype regardless of the value of constructor.
Have a look at this example:
var foo = {};
console.log(foo); // Object {}
foo.constructor = function Foo() {};
console.log(foo); // Foo {}
foo doesn't change here, it's a normal object. However, once constructor is set, it's presented as if it was an instance of Foo.
Seems that Chrome simply takes constructor property to display the Class name of the object in console.
So may create any object and simply assign any function to it's constructor property. As a result - you'll see this name in console:
var obj = { prop: 1 };
obj.constructor = function MyName() {};
will show:
...the __proto__ property points to an generic object with the methods I set in the Employee.prototype object and not the Employee.prototype object itself?
The "generic object" you're talking about is Employee.prototype. You can test this very easily yourself in Chrome by:
right-clicking on the __proto__: Object line
selecting "Store as global variable" from the menu to create a temp1 varaible
testing that temp1 == Employee.prototype is true

Why is "this" necessary when define arguments?

function Person(firstName, lastName, age)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
var family = {};
family.mother = new Person("Susan", "Doyle", 32);
…
Do we have to use "this" here? and why?
function …
{
firstName = firstName;
lastName = lastName;
age = age;
}
I wonder if this question is too simple …
in javascript the this word is a reference to the object of invocation.
So if we have a global function
function () {console.log(this);} // Window
We get the global object or window.
if we have a deeper function in an object
var obj = {f: function (){console.log(this);}};
obj.f(); // Object {f: function} we get the object that wraps the function.
This rule is broken if we use the apply invocation pattern
obj.f.apply(window); // window is now bound to this.
In your example if you were to just call
Person(); // in global scope
you would effectively be assigning
window.firstName = // ...
window.lastName = // ...
window.age = //...
Because the this keyword is bound to the window object when called from global scope
You basically created a Constructor that should be called with the new operator. The new operator wraps your function with one that creates an object and calls your function using the apply method with the object as the this parameter.
var bob = Person("bob"); // bob is undefined but you changed the window object
var sue = new Person("sue"); // sue is an object like you expect.
Examine your code
var family = {}; // make an object
family.mother = new Person("Susan", "Doyle", 32);
because you used new before you function executes js makes a new object for you and uses the apply pattern to that object. This is what happens under the hood
family.mother = {};
Person.apply(family.mother, ["Susan", "Doyle", 32]);
Here this is required to referring the current object's value.
If you don't use the this keyword the local variables get shadowed down by function parameter.
In your Person() function scope - the function parameter get higher priority than the local variable. That means inside your Person() function the by default the firstName is considered as the function parameter even though there is some field by the same name. In this case to reference the field the this keyword is used.
This is the correct way to define an object constructor. you can get reference here
The this Keyword
In JavaScript, the thing called this, is the object that "owns" the JavaScript code.
The value of this, when used in a function, is the object that "owns" the function.
The value of this, when used in an object, is the object itself.
The this keyword in an object constructor does not have a value. It is only a substitute for the new object.
The value of this will become the new object when the constructor is used to create an object.
Note that this is not a variable. It is a keyword. You cannot change the value of this.

Why to use prototype when we can just add a property

I have this javasctipt class
function employee(name, jobtitle, born)
{
this.name = name;
this.jobtitle = jobtitle;
this.born = born;
}
var fred = new employee("Fred Flintstone", "Caveman", 1970);
employee.prototype.salary = null;
fred.salary = 20000;
fred.notprototype = 1239;
console.log(fred);
now as you can see I added salary property using prototype but then I just added a property by using fred.notprototype = 1239; without the use of prototype.
when I did the console.log on object fred I see notprototype there. So Is it wrong not to add the prototype? If it is then what difference is it making?
Let's say, after all that code you add this:
var john = new employee("John Carson", "Philantropist", 2015);
console.log(john);
It will show that john has a salary attribute (of value null). You didn't set that yourself, it comes from the prototype chain.
By adding to a prototype of X, you change all objects that are created by new X().
Another example:
function School(name)
{
this.name = name;
}
School.prototype.getName = function() {
return this.name;
}
var school_one = new School('one');
console.log(school_one.getName()); // prints "one"
In this example, a method getName was added to the prototype. Upon creation of the school_one object it inherits from School.prototype all that you have added to it (in this case just that one method).
This can be used to declare the object's interface (methods you use to access it) or default values separate from the constructor.
To get a deeper understanding of JavaScript and its unique features, I highly recommend checking out a few videos from Douglas Crockford; he's a great speaker and highly knowledgeable, love listening to him :)
Properties on the prototype do two things:
for "plain" variables, they can provide a default value, which will be hidden the first time you write a property with the same name to an object
for member functions, they reduce the overhead of every instance of the object containing its own copy of that function.

Why put a constructor function directly into a variable?

Im trying to set up a variable and pass it constructor function essentailly like an anonymous type in c# but javascript doesnt seem to like it...
var aPerson = function Person(){
};
$(document).ready(function(){
Person.prototype.age = 22;
window.alert(aPerson .age);
});
Why cant I do this?
Person is only declared as part of your aPerson variable, but it needs to be defined explicitly (e.g. function Person(){}) before it can be used for prototypical inheritance. You need something more like this:
// Create a Person function object
function Person() {
};
// Modify that function's prototype
Person.prototype.age = 22;
$(document).ready(function() {
// aPerson.__proto__ = Person.prototype
var aPerson = new Person();
// JS checks whether aPerson has age already set, if not, it checks
// aPerson's prototype -- in which case it's given the value 22
alert(aPerson.age);
});
Here's the deal: the property prototype works together with new by copying the prototype reference to the object (you can see what that entails by running console.dir(aPerson) in Chrome console, for example). JavaScript checks the original object itself first, then prototype to see whether a function or property exists. That means you can change the reference prototype age later and see the changes reflected in the original object. Also, you can declare your own age in the original object itself and have that override the prototype.
I'm quite certain you have to reference your function using aPerson rather than Person (externally). Internally, you'd reference it using Person.
Alternatively, you could do this -
function Person() {
}
var aPerson = new Person();
$(function() {
Person.prototype.age = 22;
alert(aPerson.age) //22
});
because aPerson doesn't have an age. You will have to call new for it to work.
var aPerson = function Person(){
};
$(document).ready(function(){
Person.prototype.age = 22;
bPerson = new Person();
window.alert(bPerson.age);
});

Categories

Resources