Function as method in another function - javascript

I'm trying to learn JS from online tutorial - http://ejohn.org/apps/learn/#33 , you can test JS code there. I'm trying to understand nesting functions as methods inside of other functions and what "this" keyword is referencing then. Why if I put on above site code from below - it doesn't work? Could someone explain that aspect of JS?
function Ninja(name){
this.name = name;
this.changeName = function(newname) {
this.name = newname;
this.anotherFunction = function(newname2) {
this.name2 = newname2;
}
}
}
var ninja = new Ninja("John");
assert( ninja.name == "John", "The name has been set on initialization" );
// ninja.anotherFunction("Luken");
// ninja.changeName.anotherFunction("Luken");
// Why both above functions doesn't work?
assert(ninja.name2, "It works?");
ninja.changeName("Bob");
assert( ninja.name == "Bob", "The name was successfully changed." );

The value of this is determined at the time the function is invoked, not the time when it is defined. So in your code, you have to different values of this: When ninja.changeName() is called, you don't specify a value for this, so it's either undefined or whatever it might be right now.
The new operator, on the other hand, does set this before it called the function Ninja.
What you need to do is "save" the value of this inside of Ninja so the inner functions continue to use that (instead of whatever random value might be in this at the time they are called). Doing this is more simple than it sounds:
function Ninja(name){
this.name = name;
var self = this; // Create a hidden reference to "this" that is only visible in
// any functions defined before we return
self.changeName = function(newname) {
self.name = newname;
self.anotherFunction = function(newname2) {
self.name2 = newname2;
}
}
}
This works because JavaScript keeps a copy of the context (= all reachable variables) around when you define a function.

It's fairly simple:
function Ninja(name)
{//this points to Ninja object inside constructor scope
this.name = name;
this.changeName = function(newname)
{//method of Ninja, this points to context object, ie Ninja
this.name = newname;//accesses the name property of Ninja
this.anotherFunction = function(newname2)
{//defines new method for this ==> Ninja object
this.name2 = newname2;//context object is Ninja
};
};
}
var foo = new Ninja('foobar');
foo.name;//foobar
foo.changeName;//function, is defined in constructor
typeof foo.anotherFunction//undefined because it's assigned when the changeName method is called!
foo.changeName('Me');
foo.name;//Me
foo.anotherFunction('You');//works: changeName was called, and assigned anotherFunction to foo (instance of Ninja)
foo.name2;//You
What happened: simple, by invoking the changeName method, anotherFunction was defined and assigned to this. At that time this referenced the Ninja object, so the method was assigned to the instance of Ninja from which the changeName method was invoked. Prior to calling the changeName method, the anotherFunction method simply didn't exist.
Though this might seem useless or stupid, it does make sense. What you need to remember is that functions/methods are, in essence stand-alone objects. In this code, they just happen to be defined as properties/methods, but they needn't be used as such. Going back to the code above:
foo.name;//Me
bar = {};//some object
foo.changeName.apply(bar,['You']);
foo.name;//Me, nothing has changed, the changeName method was applied to the bar object
bar.name;//You, in the apply call, this pointed to bar, not foo
typeof bar.anotherFunction;//function
//You could even create the anotherFunction globally:
// JUST TO SHOW YOU CAN, THIS IS DANGEROUS
// ONLY USE THIS IF YOU KNOW WHAT THE POSSIBLE CONSEQUESES ARE!
foo.changeName.call();//in global scope
typeof antoherFunction;//function ==> this function is now globally available
The changeName method can be applied to any object, adding a new method, changeing/adding certain properties to that particular instance.

Related

Property of object not returning the expected value in Javascript [duplicate]

In C++, the language I'm most comfortable with, usually one declares an object like this:
class foo
{
public:
int bar;
int getBar() { return bar; }
}
Calling getBar() works fine (ignoring the fact that bar might be uninitialized). The variable bar within getBar() is in the scope of class foo, so I don't need to say this->bar unless I really need to make it clear that I'm referring to the class' bar instead of, say, a parameter.
Now, I'm trying to get started with OOP in Javascript. So, I look up how to define classes and try the same sort of thing:
function foo()
{
this.bar = 0;
this.getBar = function() { return bar; }
}
And it gives me bar is undefined. Changing the bar to this.bar fixes the issue, but doing that for every variable clutters up my code quite a bit. Is this necessary for every variable? Since I can't find any questions relating to this, it makes me feel like I'm doing something fundamentally wrong.
EDIT: Right, so, from the comments what I'm getting is that this.bar, a property of an object, references something different than bar, a local variable. Can someone say why exactly this is, in terms of scoping and objects, and if there's another way to define an object where this isn't necessary?
JavaScript has no classes class-based object model. It uses the mightier prototypical inheritance, which can mimic classes, but is not suited well for it. Everything is an object, and objects [can] inherit from other objects.
A constructor is just a function that assigns properties to newly created objects. The object (created by a call with the new keyword) can be referenced trough the this keyword (which is local to the function).
A method also is just a function which is called on an object - again with this pointing to the object. At least when that function is invoked as a property of the object, using a member operator (dot, brackets). This causes lots of confusion to newbies, because if you pass around that function (e.g. to an event listener) it is "detached" from the object it was accessed on.
Now where is the inheritance? Instances of a "class" inherit from the same prototype object. Methods are defined as function properties on that object (instead of one function for each instance), the instance on which you call them just inherits that property.
Example:
function Foo() {
this.bar = "foo"; // creating a property on the instance
}
Foo.prototype.foo = 0; // of course you also can define other values to inherit
Foo.prototype.getBar = function() {
// quite useless
return this.bar;
}
var foo = new Foo; // creates an object which inherits from Foo.prototype,
// applies the Foo constructor on it and assigns it to the var
foo.getBar(); // "foo" - the inherited function is applied on the object and
// returns its "bar" property
foo.bar; // "foo" - we could have done this easier.
foo[foo.bar]; // 0 - access the "foo" property, which is inherited
foo.foo = 1; // and now overwrite it by creating an own property of foo
foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that
(new Foo).foo; // is still 0
So, we did only use properties of that object and are happy with it. But all of them are "public", and can be overwritten/changed/deleted! If that doesn't matter you, you're lucky. You can indicate "privateness" of properties by prefixing their names with underscores, but that's only a hint to other developers and may not be obeyed (especially in error).
So, clever minds have found a solution that uses the constructor function as a closure, allowing the creating of private "attributes". Every execution of a javascript function creates a new variable environment for local variables, which may get garbage collected once the execution has finished. Every function that is declared inside that scope also has access to these variables, and as long as those functions could be called (e.g. by an event listener) the environment must persist. So, by exporting locally defined functions from your constructor you preserve that variable environment with local variables that can only be accessed by these functions.
Let's see it in action:
function Foo() {
var bar = "foo"; // a local variable
this.getBar = function getter() {
return bar; // accesses the local variable
}; // the assignment to a property makes it available to outside
}
var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype
foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
This getter function, which is defined inside the constructor, is now called a "privileged method" as it has access to the "private" (local) "attributes" (variables). The value of bar will never change. You also could declare a setter function for it, of course, and with that you might add some validation etc.
Notice that the methods on the prototype object do not have access to the local variables of the constructor, yet they might use the privileged methods. Let's add one:
Foo.prototype.getFooBar = function() {
return this.getBar() + "bar"; // access the "getBar" function on "this" instance
}
// the inheritance is dynamic, so we can use it on our existing foo object
foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
So, you can combine both approaches. Notice that the privileged methods need more memory, as you create distinct function objects with different scope chains (yet the same code). If you are going to create incredibly huge amounts of instances, you should define methods only on the prototype.
It gets even a little more complicated when you are setting up inheritance from one "class" to another - basically you have to make the child prototype object inherit from the parent one, and apply the parent constructor on child instances to create the "private attributes". Have a look at Correct javascript inheritance, Private variables in inherited prototypes, Define Private field Members and Inheritance in JAVASCRIPT module pattern and How to implement inheritance in JS Revealing prototype pattern?
Explicitly saying this.foo means (as you've understood well) that you're interested about the property foo of the current object referenced by this. So if you use: this.foo = 'bar'; you're going to set the property foo of the current object referenced by this equals to bar.
The this keyword in JavaScript doesn't always mean the same thing like in C++. Here I can give you an example:
function Person(name) {
this.name = name;
console.log(this); //Developer {language: "js", name: "foo"} if called by Developer
}
function Developer(name, language) {
this.language = language;
Person.call(this, name);
}
var dev = new Developer('foo', 'js');
In the example above we're calling the function Person with the context of the function Developer so this is referencing to the object which will be created by Developer. As you might see from the console.log result this is comes from Developer. With the first argument of the method call we specify the context with which the function will be called.
If you don't use this simply the property you've created will be a local variable. As you might know JavaScript have functional scope so that's why the variable will be local, visible only for the function where it's declared (and of course all it's child functions which are declared inside the parent). Here is an example:
function foo() {
var bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(f.getBar()); //'foobar'
This is true when you use the var keyword. This means that you're defining bar as local variable if you forget var unfortunately bar will became global.
function foo() {
bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(window.bar); //'foobar'
Exactly the local scope can help you to achieve privacy and encapsulation which are one of the greatest benefits of OOP.
Real world example:
function ShoppingCart() {
var items = [];
this.getPrice = function () {
var total = 0;
for (var i = 0; i < items.length; i += 1) {
total += items[i].price;
}
return total;
}
this.addItem = function (item) {
items.push(item);
}
this.checkOut = function () {
var serializedItems = JSON.strigify(items);
//send request to the server...
}
}
var cart = new ShoppingCart();
cart.addItem({ price: 10, type: 'T-shirt' });
cart.addItem({ price: 20, type: 'Pants' });
console.log(cart.getPrice()); //30
One more example of the benefits of the JavaScript scope is the Module Pattern.
In Module Pattern you can simulate privacy using the local functional scope of JavaScript. With this approach you can have both private properties and methods. Here is an example:
var module = (function {
var privateProperty = 42;
function privateMethod() {
console.log('I\'m private');
}
return {
publicMethod: function () {
console.log('I\'m public!');
console.log('I\'ll call a private method!');
privateMethod();
},
publicProperty: 1.68,
getPrivateProperty: function () {
return privateProperty;
},
usePublicProperty: function () {
console.log('I\'ll get a public property...' + this.publicProperty);
}
}
}());
module.privateMethod(); //TypeError
module.publicProperty(); //1.68
module.usePublicProperty(); //I'll get a public property...1.68
module.getPrivateProperty(); //42
module.publicMethod();
/*
* I'm public!
* I'll call a private method!
* I'm private
*/
There's a little strange syntax with the parentless wrapping the anonymous functions but forget it for the moment (it's just executing the function after it's being initialized). The functionality can be saw from the example of usage but the benefits are connected mainly of providing a simple public interface which does not engages you with all implementation details. For more detailed explanation of the pattern you can see the link I've put above.
I hope that with this :-) information I helped you to understand few basic topics of JavaScript.
function Foo() {
this.bar = 0;
this.getBar = function () { return this.bar };
}
When you call the function above with the new keyword - like this...
var foo = new Foo();
... - a few things happen:
1) an object is created
2) the function is executed with the this keyword referencing that object.
3) that object is returned.
foo, then, becomes this object:
{
bar: 0,
getBar: function () { return this.bar; }
};
Why not, then, just do this:
var foo = {
bar: 0,
getBar: function () { return this.bar; }
};
You would, if it's just that one simple object.
But creating an object with a constructor (that's how it's called) gives us a big advantage in creating multiple of the "same" objects.
See, in javascript, all functions are created with a prototype property [an object], and all objects created with that function (by calling it with the new keyword) are linked to that prototype object. This is why it's so cool - you can store all common methods (and properties, if you wanted to) in the prototype object, and save a lot of memory. This is how it works:
function Foo( bar, bob ) {
this.bar = bar;
this.bob = bob;
}
Foo.prototype.calculate = function () {
// 'this' points not to the 'prototype' object
// as you could've expect, but to the objects
// created by calling Foo with the new keyword.
// This is what makes it work.
return this.bar - this.bob;
};
var foo1 = new Foo(9, 5);
var foo2 = new Foo(13, 3);
var result1 = foo1.calculate();
var result2 = foo2.calculate();
console.log(result1); //logs 4
console.log(result2); //logs 10
That's it!
To get closer to OOP in JavaScript, you might want to take a look into a Module design pattern (for instance, described here).
Based on the closure effect, this pattern allows emulating private properties in your objects.
With 'private' properties you can reference them directly by its identifier (i.e., no this keyword as in constructors).
But anyway, closures and design patterns in JS - an advanced topic. So, get familiar with basics (also explained in the book mentioned before).
In javascript this always refers to the owner object of the function. For example, if you define your function foo() in a page, then owner is the javascript object windows; or if you define the foo() on html element <body>, then the owner is the html element body; and likewise if you define the function onclick of element <a>, then the owner is the anchor.
In your case, you are assigning a property bar to the 'owner' object at the begining and trying to return the local variable bar.
Since you never defined any local varialbe bar, it is giving you as bar is undefined.
Ideally your code should have defined the variable as var bar; if you want to return the value zero.
this is like a public access modifier of objects(variables or functions), while var is the private access modifier
Example
var x = {};
x.hello = function(){
var k = 'Hello World';
this.m = 'Hello JavaScript';
}
var t = new x.hello();
console.log(t.k); //undefined
console.log(t.m); //Hello JavaScript

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.
}
}

When I assign prototype to function I get undesired output

Please follow the code below,
var fn79 = function(){
var Student = function(_name){
this.name = _name;
};
Student.prototype = function(){
print("Inside Prototype function");
};
//Student.prototype = {}
var obj1 = new Student("Ricky");
Student.prototype.lastName = "Gonzales";
var obj2 = new Student("Jacky");
print(obj1.name+" - "+obj1.lastName);
print(obj2.name+" - "+obj2.lastName);
};
fn79();
The output I get is
D:\Rahul Shivsharan\MyPractise\JavaScriptCommandLine>java -jar js-14.jar prac.js
- Gonzales
- Gonzales
D:\Rahul Shivsharan\MyPractise\JavaScriptCommandLine>
From above output you can see I am not able to print "name" property of objects.
now if I change the the code to as below,
var fn79 = function(){
var Student = function(_name){
this.name = _name;
};
/*
Student.prototype = function(){
print("Inside Prototype function");
};
*/
Student.prototype = {}
var obj1 = new Student("Ricky");
Student.prototype.lastName = "Gonzales";
var obj2 = new Student("Jacky");
print(obj1.name+" - "+obj1.lastName);
print(obj2.name+" - "+obj2.lastName);
};
fn79();
I get the desired output as
D:\Rahul Shivsharan\MyPractise\JavaScriptCommandLine>java -jar js-14.jar prac.js
Ricky - Gonzales
Jacky - Gonzales
D:\Rahul Shivsharan\MyPractise\JavaScriptCommandLine>
Why my First example was not working properly.
Function is an object itself in javascript.
What I thought is,
Student.prototype = function(){
print("Inside Prototype function");
}
Student's prototype is pointing to function which itself is an object.
So why "name" is not getting printed in my first case, and how prototype assigning to function effects it.
The problem with functions is that they do have a non-writable .name property. This non-writability even affects the objects that inherit from the function, in your case the Student instances, so the assignment fails:
var Student = function(name){
console.log(this.name);
this.name = name;
console.log(this.name);
};
Student.prototype = function ProtoName() {};
console.log(Student.prototype.name);
new Student("test");
You'll just see the string "ProtoName" thrice.
You can use strict mode to make it more obvious that the .name = fails:
var Student = function(name){
"use strict";
this.name = name;
};
Student.prototype = function ProtoName() {};
new Student("test");
You'll get an Error: Invalid assignment in strict mode.
You can work around the non-writability by creating the .name property on the Student instance using Object.defineProperty instead of the simple assignment, but really you just should not use a function object as a prototype.
You seem to have a misunderstanding of what prototypes are and how you should use them. I will refactor your code and tell you why this works the way it works, as well as the general consensus for how to use them:
You declare a function - this is called the Constructor function. It will construct all the variables etc..
function Student(firstname, lastname){
this.firstname = firstname;
this.lastname = lastname;
}
Your prototype is an object with keys and values. This is simply because your prototype will not exist on actual products, it will act as if it's right there on the element (and not in element.prototype). We'll get to that, but for now you should keep in mind that variables are best declared inside your constructor function above, and methods are best in the prototype. You can mix them, but it's an easy divide and it keeps your code clear.
Student.prototype = {
showName: function(){ return this.firstname + ' ' + this.lastname; }
};
Now when we construct an instance of student, we can use the method showName as such:
var gonzales = new Student('Johny','Gonzales');
console.log(gonzales.showName()); // 'Johny Gonzales'
Also note that we do not mention the prototype on a consturcted object. It is still 'available' in __proto__ as it's inherited etc... But from a normal point of view this does not matter.
Variables are also directly accessible, using by simple using dot notation. By the way, keep in mind that variables and methods share the same namespace!
console.log(gonzales.firstname); // Johny
You cannot set the prototype as a function itself (unless it is a self executing function that returns an object). Functions in javascript, although considered objects, are different beasts with their own magic - do not treat them like objects as they will not treat it kindly. Don't try to do this, as it can break some Javascript inheritance and will create countless bugs you cannot squash.
For more details and accurate naming, see this article: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Custom_objects
While it is true that an function in JS in the end is also an Object, it's not the same way the other way around, since that would mean every Object is also a function.
The prototype Object holds all the functions the prototype has. This is VERY important for Object inheritance and the like.
If you think back to memory schema's it's like this:
{
hi : function hi(){}, // pointer to the function 'hi'
bye : function bye(){}, // pointer to function 'bye'
data : { planet : 'earth' } // pointer to an Object with a pointer to a String which contains 'earth'
}
If you overwrite the Object with a function, it all dies.
Mainly since JS 'knows' that a the an Objects prototype is supposed to hold functions or other objects, and does not 'execute' the prototype Object itself.
So basically, it's more like an index used by JS to find stuff that you may or may not need in an Class' instance
When you set the prototype of the Student object like this :
Student.prototype = function(){
print("Inside Prototype function");
};
The prototype of Student will be this simple function as #somethinghere pointed out, (instead of containing the function constructor and the object __proto__), so all the properties and the functions of Student will be removed. This is why the property name will be removed.
And when you add the second property lastname to Student:
Student.prototype.lastName = "Gonzales";
The prototype of Student will now has the property lastname.
And as #somethinghere pointed out :
every instance of Student will now share that last name
More informations about the prototype of an Object

Relations between an object, its constructor and its methods

this is #33 from John Resig`s Learning Advanced JavaScript. http://ejohn.org/apps/learn/#33 Would appreciate as much help as you can provide on this.
1) technically speaking, is ninja.changeName("Bob") "calling" the function Ninja, or does it go immediately to this.changeName(name);
2) Once ninja.changeName("Bob") is invoked, what is the order in which the processing events take place inside function Ninja(name)?
3) what exactly is the purpose/function of this.changeName ( name);
function Ninja(name){
this.changeName = function(name){
this.name = name;
};
this.changeName( name );
}
var ninja = new Ninja("John");
assert( ninja.name == "John", "The name has been set on initialization" );
ninja.changeName("Bob");
assert( ninja.name == "Bob", "The name was successfully changed." );
1) technically speaking, is
ninja.changeName("Bob") "calling" the
function Ninja, or does it go
immediately to this.changeName(name);
The function Ninja can be only called with the syntax Ninja(..). The syntax new Ninja(...) doesn't exactly call the function, it uses it as a constructor for a new object. And the syntax ninja.changeName("Bob") calls the anonymous function attached to the changeName property of the ninja object by its Ninja constructor. ninja.changeName("Bob") has very few things to do with the Ninja function, "technically speaking". Once the object ninja has been created, there is no relation at all between ninja.changeName and Ninja.
Returning to your question: neither. It doesn't "call" the function Ninja, and it doesn't go to this.changeName(name). It simply calls the function ninja.changeName, which is a regular, anonymous function, referenced by a property of our object ninja.
2) Once ninja.changeName("Bob") is
invoked, what is the order in which
the processing events take place
inside function Ninja(name)?
As written above, there's no relation between the two. Executing ninja.changeName("Bob") does a call on the anonymous function referenced by ninja.changeName. The association between ninja.changeName and the anonymous function function(name) { this.name=name; } has been set by the constructor Ninja, but that's the only relation between them.
3) what exactly is the
purpose/function of this.changeName (
name);
The function changeName is called in the constructor to show you that a method can be called inside the constructor. You can create setters for an object, then use these setters in the constructor to initialize the object's properties. The example is didactic ; in the real world, setters can be quite complicated, and you have to use them to initialize the object. And besides, what would be the point of creating a setter if don't use it, like in :
function Ninja(constructorArg) {
this.changeName = function(setterArg){
this.name = setterArg;
};
this.name = constructorArg; // I'm not using the setter I've just written
}
1) It is calling the method on the function.
2) It simply updates its own name property via the setter.
3) It is to use a setter to change a property.
1) technically speaking, is ninja.changeName("Bob") "calling" the function Ninja, or does it go immediately to this.changeName(name);
It calls the anonymous function that is assigned to the changeName property of the instance of Ninja that is created with var ninja = new Ninja("John");.
2) Once ninja.changeName("Bob") is invoked, what is the order in which the processing events take place inside function Ninja(name)?
The single statement in that function is run
3) what exactly is the purpose/function of this.changeName ( name);
It takes one argument, and assigns the value of that argument to the name property of the instance of Ninja on which the method is called.
this is very good question)
in JS functions are objects, so by calling ninja.changeName("Bob") you go straight to ninja's method .changeName()
if ninja.changeName was called no actions outside this method will be fired
this.changeName ( name); - is constructor actions, they are applied to ninja object on creation only (to extend the newly created object with property name)
take a look at this great book on OOP in JS

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