Local Instance Reference - javascript

In javascript say I have:
var Person = (function () {
function Person(data) {
data = $.extend({
name: "",
age: 0
}, data);
this.name = data.name;
this.age = data.age;
}
return Person;
})();
Person.prototype.getName = function () {
return this.name;
};
...if I understand the 'this' keyword correctly in javascript, it can refer to pretty much anything from the window object to itself to anything in-between (e.g. callers of the object). My question is how the heck do I write methods like .getName() so that I know I'll always have a reference to the value stored in the person object's name property if I never can be sure what 'this' will refer to in that method? Say that .getName() is called and 'this' references the window object - how the do I get the value I need then?
I'm asking because I've inherited some code using pretty heavy prototyping and I'm running into all kinds of issues trying to reference properties and methods on objects from within themselves. Seems like I'm missing something but I've been looking into scope, closures, and other patterns all day and I can't get around this.

The value of this is set by the language according to how a function/method is called.
If you have an object with a method and you do:
obj.method()
Then, this will be set to point to the object inside of the method() function.
But, if you just get that method by itself like this:
var p = obj.method;
p();
Then, because there is no object reference in the actual function call, this will be set to either window or undefined depending upon whether you are in strict mode or not.
Additionally, the caller can specify exactly what they want this to be set to using obj.method.call() or obj.method.apply() or even p.call() or p.apply() from the previous example. You can look these methods up on MDN to see more details about how they work.
So, in your previous code, this should work:
function Person(data) {
data = $.extend({
name: "",
age: 0
}, data);
this.name = data.name;
this.age = data.age;
}
Person.prototype.getName = function () {
return this.name;
};
var p = new Person({name:"John"});
var n = p.getName(); // will return "John"
Working demo: http://jsfiddle.net/jfriend00/a7MkP/
If you needed to pass getName() to a third party library that won't call it with the object context, then there are a few options like this:
Anonymous function:
var myPerson = new Person("John");
callThirdParty(function() {
// callback that calls getName with the right object context
return myPerson.getName();
});
Using .bind() (not suported in some older browsers):
var myPerson = new Person("John");
var boundFn = myPerson.getName.bind(myPerson);
callThirdParty(boundFn);
From your own method:
var self = this;
callThirdParty(function() {
// callback that calls getName with the right object context
return self.getName();
});
FYI, there really is no reason for the self-executing function you have surrounding your Person constructor function. It just makes the code more complicated and adds no value in this case.

Yes, you are understanding the this keyword correctly.
how the heck do I write methods like .getName() so that I know I'll always have a reference to the value stored in the person object's name property
You can only do so by not using this, and in not using prototyping. Give each object a unique function that always refers to the original object:
function Person(data) {
data = $.extend({
name: "",
age: 0
}, data);
this.name = data.name;
this.age = data.age;
var that = this; // a reference variable always pointing to this instance
this.getName = function() {
// using the variable from the constructor closure
return that.name; // a quite useless getter
};
}
var john = new Person({name:"John"}),
getter = john.getName;
getter(); // "John"
I'm running into all kinds of issues trying to reference properties and methods on objects from within themselves
So with the above you can solve it by making all methods instance-specific. However, that undoes all the advantages of prototyping, and should not be used.
Instead, the one who calls a function (or a method) should be responsible to call it in the correct context:
john.getName();
If you really have to pass a function to someone which ignores that (like addEventListener), you can use magic stuff like .bind() or just apply the above pattern:
// from
addEventListener("click", john.sayHello); // will call the function in context of the DOM
// to
addEventListener("click", function() {
john.sayHello(); // correct thisValue
});

Related

Constructor function - in simple namespace - Javascript

In want to define a function-constructor inside a namespace. The way in which I defined the constructor till now was a simple constructor function without NS, combined with prototypal inheritance.
The code looked kind of like:
function mySuperObject() {
var self = this;
self.p1 = "";
self.p2 = "jkejie";
// and others
}
mySuperObject.prototype.func1 = function(){...}
// and others
Introducing namespace:
After reading many articles I decided to start up with a very simple way to define a namespace, maybe the most simplest.
Basically it is just about defining a variable which points to an object-literal and the content is the object (the "mySuperObject" in the code-snippet above). The constructor function is following: mySuperObjectInNS.
The code of the object:
var MYNAMESPACE = {
//some variable outside the object
file : "ConstructorInNamespace_obj.js: ",
//Defining contructor function inside a namespace
mySuperObjectInNS : function(propOne, propTwo){
var self = this;
self.objectName = "mySuperObject";
self.propertyOne = propOne;
self.propertyTwo = propTwo;
self.doSomething = function(){
console.log(file + " doSomething called - function of object");
};
///many more functions and attributes
}
}
MYNAMESPACE.mySuperObjectInNS.prototype.specialFunction = function(){
console.log(file + " specialFunction called - prototypical inheritance defined in file of object, outside of namespace");
};
///many more functions and attributes
In another file it is possible to intantiate the object, as follows:
...
var objOne = new MYNAMESPACE.mySuperObjectInNS("param11", "40");
//following line works just fine
objOne.doSomething();
....
Questions:
It seems to me that this all is about defining an Object-Literal and
I will come into trouble the latest I am trying to define "private"
properties of that object. Is this correct?
Is that mySuperObjectInNS still a constructor function? (For me it
seems it is something else,even if I can intantiate objects from it.
Is is a very bad very bad way of namespacing or is kind of ok?
It seems to me that this all is about defining an Object-Literal and I will come into trouble the latest I am trying to define "private" properties of that object. Is this correct?
"Private properties" have nothing to do with using an object for namespacing. In fact, originally when answering this question, I read that as "private functions" because that would be relevant.
There are lots of ways to do private and semi-private properties in JavaScript, but they relate to how you create the constructor function and the methods it gives the object, not how you expose the constructor function. "Namespace" objects are about how you expose the constructor.
One common pattern for creating "private" properties is to define methods that need to access them within the constructor, and make the "properties" local variables within the constructor (so they aren't really properties at all), like this:
function SuperObject() {
var privateInformation;
this.method = function() {
// This can access `privateInformation`, which is completely
// hidden from outside the constructor
};
}
It doesn't matter at all if you do that within a "namespacing" pattern or on its own.
Private functions, on the other hand, affect the pattern. I'll show both below.
A fairly common variant that provides for private functions is to use a function to create the object, which also gives you the opportunity to create private functions:
var TheNamespace = function() {
function privateFunction() {
}
function SuperObject() {
var privateInformation;
this.method = function() {
// This can access `privateInformation`, which is completely
// hidden from outside the constructor
};
}
SuperObject.prototype.otherMethod = function() {
// Can't access `privateInformation`, but has the advantage
// that the function is shared between instances
};
return {
SuperObject: SuperObject
};
}();
// usage
var s = new TheNamespace.SuperObject();
Is that mySuperObjectInNS still a constructor function? (For me it seems it is something else,even if I can intantiate objects from it.
Yes. A constructor function is any function that expect you to use new with it.
Is is a very bad very bad way of namespacing or is kind of ok?
Using objects as pseudo-namespaces is common practice. You might also consider various asynchronous module definition (AMD) technologies, which largely make "namespace" objects largely unnecessary.
Re your comment:
You defined a self-invoking function....which returns an an object?
It's not a self-invoking function, it's an inline-invoked function, but yes, it's a function that returns an object.
(if so I think parantheses are missing)
No, we don't need any parens that aren't there because the only reason for the outer parens other places you've seen this are to tell the parser that the word function starts an expression rather than declaration; we don't need that in the above because we're already on the right-hand side of an assignment, so there's no ambiguity when function is encountered.
Due to you proposed this way, is it a better way to define the ns?
"Better" is a subjective term. It gives you a scope in which you can define private functions, which you'd asked about.
Whereas I often also saw the option: var = {} | someNSName; What is this all about?
If you have several files that will add things to the "namespace" (as is common), then you frequently see this in each of them:
var TheNamespace = TheNamespace || {};
What that does is declare the variable if it hasn't been declared before, and assign an empty object to it if it doesn't already have one. In the first file that gets loaded, this happens:
The var is processed and creates a new variable, TheNamespace, with the value undefined.
The TheNameSpace = TheNameSpace || {} assignment is processed: Since undefined is falsey, the curiously-powerful || operator results in the new {}, which gets assigned to TheNamespace.
When the next file loads, this happens:
The var is a no-op, because the variable already exists.
The TheNameSpace = TheNameSpace || {} assignment is processed: Since TheNamespace has a non-null object reference, it's truthy, and the curiously-powerful || operator results in a reference to the object TheNamespace refers to.
That is, it has no effect at all.
This is used so you can load the files in any order, or load just one file in isolation.
Here's an example:
thingy.js:
var TheNamespace = TheNamespace || {};
TheNamespace.Nifty = function() {
function privateFunction() {
}
function Nifty() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Nifty.prototype.otherMethod = function() {
// ...
};
return Nifty;
}();
thingy.js:
var TheNamespace = TheNamespace || {};
TheNamespace.Thingy = function() {
function privateFunction() {
}
function Thingy() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Thingy.prototype.otherMethod = function() {
// ...
};
return Thingy;
}();
There are lots of variations on that basic pattern, particularly if one file may add multiple things to TheNamespace. Here's one that supports doing so fairly concisely:
var TheNamespace = function(exports) {
function privateFunction() {
}
function Nifty() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Nifty.prototype.otherMethod = function() {
// ...
};
exports.Nifty = Nifty;
function Thingy() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Thingy.prototype.otherMethod = function() {
// ...
};
exports.Thingy = Thingy;
}(TheNamespace || {});

Method vs Functions, and other questions

With respect to JS, what's the difference between the two? I know methods are associated with objects, but am confused what's the purpose of functions? How does the syntax of each of them differ?
Also, what's the difference between these 2 syntax'es:
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
Also, I saw somewhere that we need to do something like this before using a function:
obj.myFirstFunc = myFirstFunc;
obj.myFirstFunc("param");
Why is the first line required, and what does it do?
Sorry if these are basic questions, but I'm starting with JS and am confused.
EDIT: For the last bit of code, this is what I'm talking about:
// here we define our method using "this", before we even introduce bob
var setAge = function (newAge) {
this.age = newAge;
};
// now we make bob
var bob = new Object();
bob.age = 30;
// and down here we just use the method we already made
bob.setAge = setAge;
To answer your title question as to what is the difference between a 'function' and a 'method'.
It's semantics and has to do with what you are trying to express.
In JavaScript every function is an object. An object is a collection of key:value pairs. If a value is a primitive (number, string, boolean), or another object, the value is considered a property. If a value is a function, it is called a 'method'.
Within the scope of an object, a function is referred to as a method of that object. It is invoked from the object namespace MyObj.theMethod(). Since we said that a function is an object, a function within a function can be considered a method of that function.
You could say things like “I am going to use the save method of my object.” And "This save method accepts a function as a parameter.” But you generally wouldn't say that a function accepts a method as a parameter.
Btw, the book JavaScript Patterns by Stoyan Stefanov covers your questions in detail, and I highly recommend it if you really want to understand the language. Here's a quote from the book on this subject:
So it could happen that a function A, being an object, has properties and methods, one of which happens to be another function B. Then B can accept a function C as an argument and, when executed, can return another function D.
There is a slight difference -
Method : Method is a function when object is associated with it.
var obj = {
name : "John snow",
work : function someFun(paramA, paramB) {
// some code..
}
Function : When no object is associated with it , it comes to function.
function fun(param1, param2){
// some code...
}
Many answers are saying something along the lines that a method is what a function is called when it is defined on an object.
While this is often true in the way the word is used when people talk about JavaScript or object oriented programming in general (see here), it is worth noting that in ES6 the term method has taken on a very specific meaning (see section 14.3 Method Definitions of the specs).
Method Definitions
A method (in the strict sense) is a function that was defined through the concise method syntax in an object literal or as a class method in a class declaration / expression:
// In object literals:
const obj = {
method() {}
};
// In class declarations:
class MyClass {
method() {}
}
Method Specificities
This answer gives a good overview about the specificities of methods (in the strict sense), namely:
methods get assigned an internal [[HomeObject]] property which allows them to use super.
methods are not created with a prototype property and they don't have an internal [[Construct]] method which means that they cannot be called with new.
the name of a method does not become a binding in the method's scope.
Below are some examples illustrating how methods (in the strict sense) differ from functions defined on objects through function expressions:
Example 1
const obj = {
method() {
super.test; // All good!
},
ordinaryFunction: function ordinaryFunction() {
super.test; // SyntaxError: 'super' keyword unexpected here
}
};
Example 2
const obj = {
method() {},
ordinaryFunction: function ordinaryFunction() {}
};
console.log( obj.ordinaryFunction.hasOwnProperty( 'prototype' ) ); // true
console.log( obj.method.hasOwnProperty( 'prototype' ) ); // false
new obj.ordinaryFunction(); // All good !
new obj.method(); // TypeError: obj.method is not a constructor
Example 3
const obj = {
method() {
console.log( method );
},
ordinaryFunction: function ordinaryFunction() {
console.log( ordinaryFunction );
}
};
obj.ordinaryFunction() // All good!
obj.method() // ReferenceError: method is not defined
A method is a property of an object whose value is a function. Methods are called on objects in the following format: object.method().
//this is an object named developer
const developer = {
name: 'Andrew',
sayHello: function () {
console.log('Hi there!');
},
favoriteLanguage: function (language) {
console.log(`My favorite programming language is ${language}`);
}
};
// favoriteLanguage: and sayHello: and name: all of them are proprieties in the object named developer
now lets say you needed to call favoriteLanguage propriety witch is a function inside the object..
you call it this way
developer.favoriteLanguage('JavaScript');
// My favorite programming language is JavaScript'
so what we name this: developer.favoriteLanguage('JavaScript');
its not a function its not an object? what it is? its a method
Your first line, is creating an object that references a function. You would reference it like this:
myFirstFunc(param);
But you can pass it to another function since it will return the function like so:
function mySecondFunction(func_param){}
mySecondFunction(myFirstFunc);
The second line just creates a function called myFirstFunc which would be referenced like this:
myFirstFunc(param);
And is limited in scope depending on where it is declared, if it is declared outside of any other function it belongs to the global scope. However you can declare a function inside another function. The scope of that function is then limited to the function its declared inside of.
function functionOne(){
function functionTwo(){}; //only accessed via the functionOne scope!
}
Your final examples are creating instances of functions that are then referenced though an object parameter. So this:
function myFirstFunc(param){};
obj.myFirst = myFirstFunc(); //not right!
obj.myFirst = new myFirstFunc(); //right!
obj.myFirst('something here'); //now calling the function
Says that you have an object that references an instance of a function. The key here is that if the function changes the reference you stored in obj.myFirst will not be changed.
While #kevin is basically right there is only functions in JS you can create functions that are much more like methods then functions, take this for example:
function player(){
this.stats = {
health: 0,
mana: 0,
get : function(){
return this;
},
set : function( stats ){
this.health = stats.health;
this.mana = stats.mana;
}
}
You could then call player.stats.get() and it would return to you the value of heath, and mana. So I would consider get and set in this instance to be methods of the player.stats object.
A function executes a list of statements example:
function add() {
var a = 2;
var b = 3;
var c = a + b;
return c;
}
1) A method is a function that is applied to an object example:
var message = "Hello world!";
var x = message.toUpperCase(); // .toUpperCase() is a built in function
2) Creating a method using an object constructor. Once the method belongs to the object you can apply it to that object. example:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.name = function() {return this.firstName + " " + this.lastName;};
}
document.getElementById("demo").innerHTML = person.fullName(); // using the
method
Definition of a method: A method is a property of an object that is a function. Methods are defined the way normal functions are defined, except that they have to be assigned as the property of an object.
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
are (almost) identical. The second is (usually) just shorthand. However, as this jsfiddle (http://jsfiddle.net/cu2Sy/) shows, function myFirstFunc will cause the function to be defined as soon as the enclosing scope is entered, whereas myFirstFunc = function will only create it once execution reaches that line.
As for methods, they have a this argument, which is the current object, so:
var obj = {};
obj.func = function( ) {
// here, "this" is obj
this.test = 2;
}
console.log( obj.test ); // undefined
obj.func( );
console.log( obj.test ); // 2
The exact syntax you showed is because you can also do this:
function abc( ) {
this.test = 2;
}
var obj = {};
obj.func = abc;
obj.func( ); // sets obj.test to 2
but you shouldn't without good reason.
ecma document
4.3.31method :
function that is the value of a property
NOTE When a function is called as a method of an object, the object is
passed to the function as its this value.
It is very clear: when you call a function if it implicitly has a this (to point an object) and if you can't call the function without an object, the function deserves to name as method.

OOP. Calling methods from within methods

How do I call class methods from functions within the class? My code is:
var myExtension = {
init: function() {
// Call onPageLoad
},
onPageLoad: function() {
// Do something
},
}
I've tried ...
onPageLoad();
... from within the init method but it's saying it's not defined.
I'm not having much luck with google because I don't understand the syntax used. All the JS OOP examples I find online are in a different format. I'm using the format Mozilla use for extension development.
The object the current method was invoked on is available via the special variable this. Any time you call a method on an object, this will refer, within the method, to the object.
var myExtension = {
init: function() {
this.onPageLoad();
},
onPageLoad: function() {
// Do something
},
};
this always refers to the calling object rather than the object the function is defined on or is a property of.
value = 'global';
var ob0 = {
value: 'foo',
val: function() {
return this.value;
},
},
ob1 = {value: 'bar'},
ob2 = {value: 'baz'};
ob0.val(); // 'foo'
ob1.val = ob0.foo;
ob1.val(); // 'bar'
ob0.val.call(ob2); // 'baz'
var val = ob0.val;
val(); // 'global'
In the last case, val is executed as a free function (a function that isn't bound to an object, i.e. not a method), in which case this takes on the value of the global object (which is window in web browsers) within the execution of val. Global variables are actually properties of the global object, hence val() returns 'global' (the value of the global variable named value). Since global variables are actually properties of the global object, you can view free functions as actually being methods of the global object. From this viewpoint, the last two lines (when executed in global scope) are equivalent to:
window.val = ob0.val;
window.val();
This viewpoint doesn't exactly match the reality of scoping, though you'll only notice the difference within functions. In a function, window.val = ... will create a global while var val won't.
value = 'global';
var ob0 = {
value: 'foo',
val: function() {
return this.value;
},
};
function lcl() {
var val = ob0.val; // doesn't set a global named `val`
return val(); // 'global'
}
lcl(); // 'global'
val(); // error; nothing named 'val'
function glbl() {
window.val = ob0.val; // sets a global named `val`
return window.val(); // 'global'
}
glbl(); // 'global'
val(); // 'global'
See MDN's reference page for more on the call method used above. For more on the this variable, see "JavaScript “this” keyword" and "How does “this” keyword work within a JavaScript object literal?"
Assuming that you have called init like this:
myExtension.init();
then it should be:
init: function() {
// before
this.onPageLoad();
// after
}
But in Javascript functions are not actually bound to objects and you can call any function on any other object, like this:
myExtension.init.call(anotherObject); // or
myExtension.init.apply(anotherObject);
In this example this within init would be anotherObject, which doesn't have onPageLoad defined. If you want to support this kind of usage you'll have to manually reference the initial object:
init: function() {
// before
myExtension.onPageLoad();
// after
}
In Javascript you need to explicitly mention the this
this.onPageLoad()
The same is also true for other member variables (remember that in Javascript methods are just member variables that happen to be functions)
this.memberVariable
Have you considered a closure, instead?
For example:
var myExtension = ( function() {
var me = {};
var private_thingy = "abcDEFG123";
var onPageLoad = function() {
// do page loading business
alert( private_thingy );
}
me.onPageLoad = onPageLoad;
var init = function() {
onPageLoad();
}
me.init = init;
return me;
})();
///////////////
myExtension.private_thingy = "DIDDLED!";
// will NOT modify the private_thingy declared within the closure
myExtension.init(); // will work fine.
Anything you define within the closure is available within the closure at all times, and when implemented carefully will yield private members not accessible to users of the object. Only members that you explicitly export - e.g., the me.xxx = xxx lines - are publicly available.
Thus, when onPageLoad executes, "abcDEFG123" will be displayed in the alert, not "DIDDLED!". Users of the object can modify properties using the dot operator until the cows come home; what's not made public by the closure, however, can never be modified: even if the user reassigns a function on the public interface, calls to the private function from within the closure will always point to the function defined within the closure.
The important part: it unties you from the constant use of this (unless you really want to use it; save your fingers for more important typing!).
Give it a shot. And have a look at Javascript: The Good Parts by Crockford.

Confusing JavaScript statement: "var x = new this();"

I thought I understood the concept of the JavaScript prototype object, as well as [[proto]] until I saw a few posts regarding class inheritance.
Firstly, "JavaScript OOP - the smart way" at http://amix.dk/blog/viewEntry/19038
See the implementation section:
var parent = new this('no_init');
And also "Simple JavaScript Inheritance" on John Resig's great blog.
var prototype = new this();
What does new this(); actually mean?
This statement makes no sense to me because my understand has been that this points to an object and not a constructor function. I've also tried testing statements in Firebug to figure this one out and all I receive is syntax errors.
My head has gone off into a complete spin.
Could someone please explain this in detail?
In a javascript static function, you can call new this() like so,
var Class = function(){}; // constructor
Class.foo = function(){return this;} // will return the Class function which is also an object
Therefore,
Class.foo = function(){ return new this();} // Will invoke the global Class func as a constructor
This way you get a static factory method. The moral of the story is, not to forget functions are just like any other objects when you are not calling them.
What is confusing you, I think, is just where "this" is really coming from. So bear with me-- here is a very brief explanation that I hope will make it quite clear.
In JavaScript, what "this" refers to within a function is always determined at the time the function is called. When you do:
jimmy.nap();
The nap function (method) runs and receives jimmy as "this".
What objects have references to nap is irrelevant. For example:
var jimmy = {}, billy = {};
jimmy.nap = function(){ alert("zzz"); };
var jimmy_nap = jimmy.nap;
jimmy_nap(); // during this function's execution, this is *NOT* jimmy!
// it is the global object ("window" in browsers), which is given as the
// context ("this") to all functions which are not given another context.
billy.sleep = jimmy.nap;
billy.sleep(); // during this function's excution, this is billy, *NOT* jimmy
jimmy.nap(); //okay, this time, this is jimmy!
In other words, whenever you have:
var some_func = function(arg1, arg2){ /*....*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(2, 3);
other_obj.some_meth(2, 3);
What it's getting "translated" into (not literally-- this is pedagogical, not about how javascript interpreters actually work at all) is something like:
var some_func = function(this, arg1, arg2){ /* ...*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(obj, 2, 3);
other_obj.some_meth(other_obj, 2, 3);
So, notice how extend is used in the example on that page:
UniversityPerson = Person.extend({ /* ... */ });
Pop quiz: When extend runs, what does it think "this" refers to?
Answer: That's right. "Person".
So the puzzling code above really is the same as (in that particular case):
var prototype = new Person('no_init');
Not so mysterious anymore, eh? This is possible because unlike in some languages,
a JavaScript variable-- including "this"-- can hold any value, including a function such as Person.
(There is nothing that makes Person specifically a constructor. Any function can be invoked with the new keyword. If I recall the exact semantics, I think they are that when a function is called with the new keyword, it is automatically given an empty object ({}) as its context ("this") and when the function returns, the return value is that same object unless (maybe?) the function returns something else)
This is a cool question because it speaks to a pretty essential part of JavaScript's neatness or oddness (depending on how you see it).
Does that answer your question? I can clarify if necessary.
AJS.Class effectively* translates this:
var Person = new AJS.Class({
init: function(name) {
this.name = name;
Person.count++;
},
getName: function() {
return this.name;
}
});
Person.count = 0;
into this:
var Person = function (name) {
this.name = name;
Person.count++;
};
Person.prototype = {
getName: function() {
return this.name;
}
};
Person.extend = AJS.Class.prototype.extend;
Person.implement = AJS.Class.prototype.implement;
Person.count = 0;
Therefore, in this case, this in AJS.Class.prototype.extend refers to Person, because:
Person.extend(...);
// is the same as
Person.extend.call(Person, ...);
// is the same as
AJS.Class.prototype.extend.call(Person, ...);
* There are a lot of cases I don't go over; this rewrite is for simplicity in understanding the problem.
Imagine the following situation :
var inner = function () {
var obj = new this;
console.log(obj.myProperty);
};
var f1 = function () {
this.myProperty = "my Property"
}
f1.f2 = inner;
f1.f2();
Here the calling object is itself a function, so this will return a function, and we can instantiate it.
In order to use this()(not this) the outer function(the context) must itself return smth that can be instantiated(another function):
var inner = function () {
var obj = new this();
console.log(obj.myProperty);
};
var f1 = function () {
var func = function () {};
func.myProperty = 'my property';
return func;
};
f1.f2 = inner;
f1.f2();
A simpler code explaination:
class User {
constructor() {
this.name = '';
this.age = '';
}
static getInfo() {
let user = new this();
console.log(user);
}
}
User.getInfo()
Output:
Object {
age: "",
name: ""
}
see this link http://www.quirksmode.org/js/this.html It will tell you about the this keyword, but I am not sure what this() is, may be its some kind of user defined function...... that you are not aware of...
"this" means the context of the function currently running.
The code you are posting surely appears in a function that act as a method for an object.
So the object is the context of the function.
"new this()" will return a clone of the current object after running its constructor function with the passed arguments.
this() refers to the the function that the code is in, but this() would have to be within that function. Calling new this(); within a function would create a never ending loop. Calling it outside of a function would be redundant because there is no function/class set as this().

Setting javascript prototype function within object class declaration

Normally, I've seen prototype functions declared outside the class definition, like this:
function Container(param) {
this.member = param;
}
Container.prototype.stamp = function (string) {
return this.member + string;
}
var container1 = new Container('A');
alert(container1.member);
alert(container1.stamp('X'));
This code produces two alerts with the values "A" and "AX".
I'd like to define the prototype function INSIDE of the class definition. Is there anything wrong with doing something like this?
function Container(param) {
this.member = param;
if (!Container.prototype.stamp) {
Container.prototype.stamp = function() {
return this.member + string;
}
}
}
I was trying this so that I could access a private variable in the class. But I've discovered that if my prototype function references a private var, the value of the private var is always the value that was used when the prototype function was INITIALLY created, not the value in the object instance:
Container = function(param) {
this.member = param;
var privateVar = param;
if (!Container.prototype.stamp) {
Container.prototype.stamp = function(string) {
return privateVar + this.member + string;
}
}
}
var container1 = new Container('A');
var container2 = new Container('B');
alert(container1.stamp('X'));
alert(container2.stamp('X'));
This code produces two alerts with the values "AAX" and "ABX". I was hoping the output would be "AAX" and "BBX". I'm curious why this doesn't work, and if there is some other pattern that I could use instead.
EDIT: Note that I fully understand that for this simple example it would be best to just use a closure like this.stamp = function() {} and not use prototype at all. That's how I would do it too. But I was experimenting with using prototype to learn more about it and would like to know a few things:
When does it make sense to use prototype functions instead of closures? I've only needed to use them to extend existing objects, like Date. I've read that closures are faster.
If I need to use a prototype function for some reason, is it "OK" to define it INSIDE the class, like in my example, or should it be defined outside?
I'd like to understand why the privateVar value of each instance is not accessible to the prototype function, only the first instance's value.
When does it make sense to use prototype functions instead of closures?
Well, it's the most lightweight way to go, let's say you have a method in the prototype of certain constructor, and you create 1000 object instances, all those objects will have your method in their prototype chain, and all of them will refer to only one function object.
If you initialize that method inside the constructor, e.g. (this.method = function () {};), all of your 1000 object instances will have a function object as own property.
If I need to use a prototype function for some reason, is it "OK" to define it INSIDE the class, like in my example, or should it be defined outside?
Defining the members of a constructor's prototype inside itself, doesn't makes much sense, I'll explain you more about it and why your code doesn't works.
I'd like to understand why the privateVar value of each instance is not accessible to the prototype function, only the first instance's value.
Let's see your code:
var Container = function(param) {
this.member = param;
var privateVar = param;
if (!Container.prototype.stamp) { // <-- executed on the first call only
Container.prototype.stamp = function(string) {
return privateVar + this.member + string;
}
}
}
The key point about your code behavior is that the Container.prototype.stamp function is created on the first method invocation.
At the moment you create a function object, it stores the current enclosing scope in an internal property called [[Scope]].
This scope is later augmented when you call the function, by the identifiers (variables) declared within it using var or a FunctionDeclaration.
A list of [[Scope]] properties forms the scope chain, and when you access an identifier (like your privateVar variable), those objects are examined.
And since your function was created on the first method invocation (new Container('A')), privateVar is bound to the Scope of this first function call, and it will remain bound to it no matter how do you call the method.
Give a look to this answer, the first part is about the with statement, but in the second part I talk about how the scope chain works for functions.
Sorry for resurrecting an old question, but I wanted to add something that I recently discovered somewhere else here on SO (looking for the link, will edit/add it once I find it): found it.
I personally like the below methodology because I can visually group all my prototype and 'instance' definitions together with the function definition, while avoiding evaluating them more than once. It also provides an opportunity to do closures with your prototype methods, which can be useful for creating 'private' variables shared by different prototype methods.
var MyObject = (function () {
// Note that this variable can be closured with the 'instance' and prototype methods below
var outerScope = function(){};
// This function will ultimately be the "constructor" for your object
function MyObject() {
var privateVariable = 1; // both of these private vars are really closures specific to each instance
var privateFunction = function(){};
this.PublicProtectedFunction = function(){ };
}
// "Static" like properties/functions, not specific to each instance but not a prototype either
MyObject.Count = 0;
// Prototype declarations
MyObject.prototype.someFunction = function () { };
MyObject.prototype.someValue = 1;
return MyObject;
})();
// note we do automatic evalution of this function, which means the 'instance' and prototype definitions
// will only be evaluated/defined once. Now, everytime we do the following, we get a new instance
// as defined by the 'function MyObject' definition inside
var test = new MyObject();
You need to put the function on each specific instance instead of the prototype, like this:
Container = function(param) {
this.member = param;
var privateVar = param;
this.stamp = function(string) {
return privateVar + this.member + string;
}
}
To get the behavior you want you need to assign each individual object separate stamp() functions with unique closures:
Container = function(param) {
this.member = param;
var privateVar = param;
this.stamp = function(string) {
return privateVar + this.member + string;
}
}
When you create a single function on the prototype each object uses the same function, with the function closing over the very first Container's privateVar.
By assigning this.stamp = ... each time the constructor is called each object will get its own stamp() function. This is necessary since each stamp() needs to close over a different privateVar variable.
That is because privateVar is not a private member of the object, but part of stamp's closure. You could get the effect by always creating the function:
Container = function(param) {
this.member = param;
var privateVar = param;
this.stamp = function(string) {
return privateVar + this.member + string;
}
}
The value of privateVar is set when the function is built, so you need to create it each time.
EDIT: modified not to set the prototype.

Categories