accessing vars inside a js function - javascript

So I have a pseudo class with functions and vars inside of it. For example:
function MyClass()
{
this.a = 0;
this.b = function(c)
{
this.a += c;
}
}
Then, when I go to use it later I'll do this:
var myObject = new MyClass();
myObject.b(3);
myObject.b(5);
but when I do this:
console.log("A: " + myObject.a);
I get:
A: 0
What am I doing wrong?
Here's my actual code. It's split into mutiple files but I'll put up the ones that are relevant:
function SongDatabase() {
this.songs = new Array();
this.loadSongs = function () {
};
this.saveSongs = function () {
};
var _Constructor_ = function () {
var mySong = new Song();
this.songs = new Array(mySong);
};
_Constructor_();
}
function LyriX() {
var songDatabase = new SongDatabase();
//var playlistDatabase = new PlaylistDatabase();
songDatabase.loadSongs();
var sourceList = new ScrollableList();
sourceList.setElement($S.getElement("sourceList"));
var accessoryList = new ScrollableList();
accessoryList.setElement($S.getElement("accessoryList"));
var sourceListClick = function (index) {
$S.log("source click: " + index);
if (index == 0) {
displaySongs();
}
};
sourceList.setClickListener(sourceListClick);
var displaySongs = function () {
$S.log("display songs");
// STACK OVERFLOW LOOK HERE!!! thanks :)
// in debug in chrome songDatabase.songs is a zero length array
accessoryList.loadArray(songDatabase.songs);
};
}
$S.addOnLoadListener(function () {
new LyriX();
});

One issue:
> var _Constructor_ = function () {
> var mySong = new Song();
> this.songs = new Array(mySong);
> };
> _Constructor_();
In the above, when _Constructor_ is called as a function, you don't set its this value so it defaults to the global object (in non-strict mode, or undefined in strict mode). So songs becomes a global variable or throws an error in strict mode.
It seems like fairly useless function anyway, consider:
this.songs = [ new mySong() ];

I see someone's taking the "Java" in JavaScript too literally. :)
A couple things you should know about JavaScript:
In JavaScript, arrays don't work like they do in other languages.
They're a lot more like dictionaries then what you would call an array in C or Java;
they're not significantly more memory efficient, or faster;
no preallocation is done;
there's no offeset, etc, in the low-level implementation.
JavaScript arrays are little more than a convenient (but useful!) structure
for holding order-imperative data.
Arrays can be created using the new Array(length) expression,
or the simple literal expression, [].
Generally, you'll want to use the array literal, [].
Using new Array(length) doesn't really do anything useful;
it sets the initial length property of the array, but that's basically it.
All elements remain undefined.
There are no additional constraints or bounds checking.
You can do a[100] = 'whatever' on an array created by calling var a = new Array(5)
and the interpreter won't bat an eye.
JavaScript uses prototypal inheritance which is significantly different then the
classical inheritance model used in languages like C++ and Java.
With these points in mind, lets examine the following code block:
function SongDatabase() {
this.songs = new Array();
this.loadSongs = function () {
// etc.
};
this.saveSongs = function () {
// etc.
};
var _Constructor_ = function () {
var mySong = new Song();
this.songs = new Array(mySong);
};
_Constructor_();
}
This block of code is probably not doing what you think it's doing.
By initializing the SongDatabase methods inside the SongDatabase() function
you're creating new method functions for every instance of songDatabase.
This may not be a big deal when you're dealing with a couple of dozen of instances,
but if you're dealing with hundreds, the extra memory required can become a problem.
You'll want to use the prototype pattern here, instead (see below).
Your _Constructor_ function isn't doing anything.
var mySong = new Song() creates a new mySong object
local to the _Constructor_ function and not accessible outside of it.
When the _Constructor_ invocation returns,
it's mySong variable is garbage collected (like any other local variable would be).
_Constructor_ is a private function and not a method;
I'm not entirely sure what this in that context will reference.
You may end up creating a songs property on the global object
(but I'd want to test that to be sure).
As I mentioned earlier, when you call Array() with the new operator,
it takes an optional argument that sets the initial length of the array.
In this case, the interpreter will try to coerce mySong into a number
(mySong is not added to the array!);
when that fails it will simply return a new array with length = 0.
Instead, you're better off writing SongDatabase() like so:
function SongDatabase() {
this.songs = [];
// etc.
}
SongDatabase.prototype.loadSongs = function () {
// load songs into `this.songs`
};
SongDatabase.prototype.saveSongs = function () {
// save songs loaded into `this.songs`
};
The prototypal pattern may look strange,
but its probably the best way to handle your use case.
You'll still have direct access to then songs array (which may or may not be important),
and by attaching the loadSongs and saveSongs functions to SongDatabase's prototype
you ensure that those functions are shared.

function MyClass()
{
this.a = 0;
this.b = function(c)
{
this.a += c;
}
}
change a+=c into this.a+=c;

Variables are not bound to "classes", as in other languages. Think of it as an object with properties. A single a just references a variable "a" (not declared with var in the function, so even global in here). You want to update the property "a" of the this object, use this.a instead (the dot operator to access the property). You also may want to read Working with objects.
After your edit (you say you'd been using this.a), it works for me: http://jsfiddle.net/WKuZe/
After you provided us your real code, I noticed this odd structure:
function SongDatabase() {
this.songs = new Array();
// some methods
var _Constructor_ = function () {
var mySong = new Song();
this.songs = new Array(mySong);
};
_Constructor_();
}
A constructor like SongDatabase is (with the new keyword) called with the new instance as this. A normal function is usually called on nothing, i.e. this is undefined or the global object in non-strict mode. See documentation for the this keyword on MDN.
In here, you first initialisize the songDatabases' songs property with an empty array. Then, in the _Constructor_ function, you create an other array with one song but assign it to window.songs, because the function is not called on the songDatabase instance. The same problems may occur in your loadSongs() method. Apart from calling and binding the usual method to provide a "static" reference to the instance object is a scoped variable:
function SongDatabase() {
var that = this; // <== always points to the instance
// some methods
function _Constructor_ () {
var mySong = new Song();
that.songs = new Array(mySong);
// ^^^^
};
_Constructor_();
}
If your _Constructor_ is not a local function, but maybe a interface-adding global function, you might provide the instance (this) as an argument or use _Constructor_.call(this), which allows the use of the this keyword as if _Constructor_ were a "class".

Related

Why is the 'this' keyword needed in objects

From sololearn
function mathCalc (height, weight) {
this.height = height;
this.weight = weight;
// this.sampleCalc = ; (taken out)
}
Why do I need to do:
this.height = height;
this.weight = weight;
What is the reason behind it?
this is a keyword for the function's caller for function expressions and function declarations. For constructor functions (which I will demonstrate below) and object methods, this refers to the object itself. Here are examples of the types mentioned:
function myFunc() { return this; } //function declaration
const myVar = function() { return this; } //function expression
const obj = {a: 1, whatIsA: function() { return this.a } } //whatIsA is an object method
If you call either of the above functions from the global context (not inside another function), this is the Window object. The browser defaults this to the Window (which when you think about it, is the caller of the function since your browser ran the file).
myFunc(); //outputs "Window" obj
myVar(); //also outputs "Window" obj
For constructor functions instantiated with new, this is bound to the newly created object.
I think the best way to show why this is so useful is to give an example. Examine the following code:
function Dog(name) {
this.name = name;
this.bones = 0;
this.addBone = function(numOfBones) {
this.bones += numOfBones;
return this;
}
}
const clifford = new Dog('Clifford');
We have a constructor function (meaning we're going to be creating new objects from this function) called Dog.
Consider what happens when we create a new Dog named "Clifford". The new keyword creates a brand new object in memory for Clifford, which is an instance of the Dog constructor function. So since we created something that didn't exist before, this refers to the object itself. If we replaced this.name = name with let myName = name what would happen? We wouldn't be able to access myName because myName isn't part of our brand new instance of the Dog object.
Let's give Clifford a few bones.
clifford.addBone(1).addBone(2).addBone(3);
console.log(clifford.bones); //outputs 6
How is it possible we can chain methods as we did above? Because the method returns this!
When a function is called as a method of an object, its this is set to the object the method is called on.
So we're returning the object after adding a bone to Clifford's bones. This gives us back the object itself again.
Arrow functions behave slightly differently. this is inherited from the current lexical scope and not the caller.
height and weight are only parameters for the arguments passed into the function. If you're learning, it might help to use different names.
this refers to the function itself. When treated as an object/class, it will retain the values. Notice in the object output below that h and w are not retained, height and weight are. Also notice that one and two have different values, the same value that was passed into the function when they were initialized.
function mathCalc (h, w) {
this.height = h
this.weight = w
}
let one = new mathCalc(1,3)
let two = new mathCalc(2,4)
console.log('one:',one)
console.log('two:',two)
For a function that only gets called once, it makes complete sense to avoid this. However, for persistent state, this can be useful. Note that this only gets rebound when the new keyword is used.
function Worm() {
this.size = 1;
this.grow = function() {
++this.size;
}
}
const wormy = new Worm();
console.log(wormy.size);
wormy.grow();
console.log(wormy.size);
With ES6 Javascript, there is a much cleaner way to take advantage of this.
class Worm {
constructor() {
this.size = 1;
}
grow() {
++this.size
}
}
In short this is the owner object of the function. If you had two objects or elements that called upon a function - how would you place the appropriate value in the appropriate element that called it? Using this can eliminate the need for duplicate code etc.
Technically you don't HAVE to use it; but it has its uses.
You can read more here or here.
Here's a little click test snippet, where I can have one function for alerting this clicked div id rather than having to write one for each div;
var div = document.getElementsByTagName('div');
var i;
for (i = 0; i < div.length; ++i) {
div[i].onclick = function() {
alert(this.id);
}
}
<div id="test1">Click Test 1</div>
<div id="test2">Click Test 2</div>
<div id="test3">Click Test 3</div>
Mind you, this is easier in jQuery - but I didn't feel the need to include the CDN for this example. However, it would look something like this;
$('div').on('click', function() {
alert(this.id);
})
it's an easier way to write the name of an object, useful for larger programs that have many objects.

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 || {});

JavaScript new Function confusion

While reading Learning JavaScript 2nd edition, I see a block of code in Chapter 13: Creating Custom JavaScript Objects.
var oneOff = new Function () {
this.variablea = "variablea";
this.method = function () {
return xxx;
}
}
It is said that it is the same as:
var oneOff = new Object();
oneOff.variablea = "variablea";
oneOff.method = function () {...};
But I don't know what new Function () {..} is. Any help is appreciated. Thanks.
When using new function() { /* */ }, you are not creating a new function, but rather an object.
It is just a standard use of new with a constructor function, like in :
var oneInstance = new ConstructorFunction();
function ConstructorFunction() {
this.var1 = 'val1';
this.method1 = function() { } ;
}
The difference is that the constructor is defined right at the time of instantiation, and we omit to call the function, which is legal (although confusing i think).
I find it somehow clearer with some brackets, and making explicit the call to the constructor :
var oneOff = new ( function () {
this.variablea = "variablea";
this.method = function () {
return xxx;
};
} ) () ;
but for creating just one single object, one would rather use the simple object notation :
var oneOff = {
variablea : 'valuea',
method : function () { return xxx; }
}
How do they compare in performances ?
For the new function() {} method, creating the object will require to first create a function, then execute that function within a 'new' context.
On the other hand, object litteral just create ...one object, so it's less time and less garbage created.
On use performances of the two types of objects (time to read/write a property /use a method) it's very hard to say since all javascript interpreters are very complex and very different. When and how do they decide to optimize a part of the code is something you can't really know before benchmarking. - And benchmarking is not an easy task also because of those 'random' optimisations. My bet is that they should be very close in use performance, let us know if you take the time to do some measures.
new function (notice F is lowercase) is one of the many ways of creating an object in Javascript. After the code is interpreted an object will be assigned to oneOff with variablea and method properties.
Another way to achieve this is to use the object literal notation:
var oneOff = {
variablea:"variablea",
method:function () {
return xxx; //this will be undefined
}
}
This works fine if you only need one instance of oneOff however if you need multiple instances of oneOff you can use the function constructor as follows:
function OneOff(){
this.variablea = "variablea";
}
OneOff.prototype.method = function(){
return xxx; //one again undefined
}
var firstOneOff = new OneOff();
var secondOneOff = new OneOff();

build an object without using of "new"

How can this object be rewritten so you don't need to declare it with "new"?
var Lang = new function(){
this.get = function(str, trans){
if(TRANSLATE[str]){
var str = TRANSLATE[str][LANG];
if(count_obj(trans) > 0){
for(var key in trans){
str = str.replace('%'+key+'%', trans[key]);
}
}
}
return str;
};
};
To something like this:
var Lang = {
get : function(){}
};
You wrote the solution to your own question in the question...this is a perfectly valid way to create an object in javascript:
var Lang = {
get: function(str, trans){
if(TRANSLATE[str]){
var str = TRANSLATE[str][LANG];
if(count_obj(trans) > 0){
for(var key in trans){
str = str.replace('%'+key+'%', trans[key]);
}
}
}
return str;
};
};
If you want private variables, the usual way to do that is to create a function with local variables that return the object with those variables encapsulated in a closure like so:
var Lang = (function() {
var p1; // private variable
var p2; // another private variable
return {
getP1: function () {
return p1;
},
setP1: function(value) {
p1 = value;
}
};
})();
Note that the function that creates the object you want is executed right away and returns the object with two private variables captured in the closure. Those variables will not be accessible from outside the object.
Patterns for Enforcing new
As mentioned already, constructors are still just functions but invoked with new.
What
happens if you forget new when you invoke a constructor? This is not going to cause
syntax or runtime errors but might lead to logical errors and unexpected behavior.
That’s because when you forget new, this inside the constructor will point to the global
object. (In browsers this will point to window.)
When your constructor has something like this.member and you invoke the constructor
without new, you’re actually creating a new property of the global object called
member and accessible through window.member or simply member. This behavior is highly
undesirable, because you know you should always strive for keeping the global namespace
clean.
// constructor
function Waffle() {
this.tastes = "yummy";
}
// a new object
var good_morning = new Waffle();
console.log(typeof good_morning); // "object"
console.log(good_morning.tastes); // "yummy"
// antipattern:
// forgotten `new`
var good_morning = Waffle();
console.log(typeof good_morning); // "undefined"
console.log(window.tastes); // "yummy"
Self-Invoking Constructor
To address the drawback of the previous pattern and have prototype properties available
to the instance objects, consider the following approach. In the constructor you
check whether this is an instance of your constructor, and if not, the constructor invokes
itself again, this time properly with new:
function Waffle() {
if (!(this instanceof Waffle)) {
return new Waffle();
}
this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;
// testing invocations
var first = new Waffle(),
second = Waffle();
console.log(first.tastes); // "yummy"
console.log(second.tastes); // "yummy"
console.log(first.wantAnother); // true
console.log(second.wantAnother); // true
Another general-purpose way to check the instance is to compare with
arguments.callee instead of hard-coding the constructor name.
if (!(this instanceof arguments.callee)) {
return new arguments.callee();
}
This pattern uses the fact that inside every function, an object called arguments is created
containing all parameters passed to the function when it was invoked. And arguments
has a property called callee, which points back to the function that was called. Be
aware that arguments.callee is not allowed in ES5’s strict mode, so it’s best if you limit
its future use and also remove any instances should you find them in existing code.
“JavaScript Patterns, by Stoyan Stefanov (O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.”
just leave the "new" out, rest is the same. :)
var Lang = function(){
...
}
Edit: example copy-paste from firebug, "dsa" is just an object, "dsaFunc" is a function, but you can do the same with them:
>>> var dsa = {};
undefined
>>> dsa.get = function(a){ return a+1;}
function()
>>> dsa.get(2)
3
>>> var dsaFunc = function(){};
undefined
>>> dsaFunc.get = function(a){ return a+1;}
function()
>>> dsaFunc.get(2)
3

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().

Categories