let variables in classes with "this" context [duplicate] - javascript

This question already has answers here:
Javascript: Do I need to put this.var for every variable in an object?
(6 answers)
Closed 5 years ago.
So I have a question about this and just having normal variables in classes.
Normally we do something like this:
class Thingy {
constructor(thing) {
this.id = thing
}
printID() {
console.log(this.id)
}
}
let newthingy = new Thingy("ID1")
let newthingy2 = new Thingy("ID2")
newthingy.printID()
newthingy2.printID()
Which works just fine, however something like this will not:
class Thingy {
constructor(thing) {
let id = thing
}
printID() {
console.log(id)
}
}
let newthingy = new Thingy("ID1")
let newthingy2 = new Thingy("ID2")
newthingy.printID()
newthingy2.printID()
So I understand that newthingy will have no idea what id is, so won't it just look up the prototype chain back at the original class prototype? I realize it probably wouldn't get the right id but how come we get a id not defined error, should it attempt to look up the prototype chain first?

I believe it is all about scope. When you say...
let id = thing
... you are actually declaring a variable that is local to the constructor method. When you define ...
this.id = thing
... it is actually modifying a property value of the Thingy instance. And, when printID tries to access "id", it has no context to find "id" in.

This has absolutely nothing to do with the prototype. It's much simpler than you may make it out to be:
"Class methods" are merely functions which act on an object. The way they act on an object is through this. That is all. It's a normal function, which has implicit access to this, which is an object. Since in Javascript the value of this is decided at call time, this is an extremely malleable mechanism:
function foo() {
console.log(this.bar);
}
foo.call({ bar: 'baz' });
let baz = { bar: 'baz' };
baz.foo = foo;
baz.foo();
As you see, you don't even need a class for this to work. A class merely formalises this into a certain pattern:
new Thingy creates a new object and calls the Thingy constructor on it, in the constructor you set this.id = thing, creating the id property on that new object. When you then call newthingy.printID(), you're calling the printID function setting its this context to the object created previously (newthingy), so this.id works.
The id value is transported from constructor to printID as a property on an object. If you just use id (instead of this.id), you're merely trying to access a local variable which doesn't exist.

'constructor' and 'printID' are both functions.Variables defined at them cannot be reached by others.

Related

What is it called when a function behaves like a class but doesn't use the class keyword, nor "new" keyword (in Javascript)?

I looked through the suggested links but can't seem to find the term for a function that acts like a class (is it a constructor function? doesn't have that keyword either!) but doesn't use the new keyword, nor class.
I've used both this example's pattern and the class pattern in my code but realized I don't know how to describe the former.
I think this is in part because I learned JS recently, have seen class thrown around a lot, yet looking through my notes of not-ES5,6,7,2018,2020 etc. can't seem to find what var aCounter = counterFunction() is called for the life of me.
I know what the result of what i'm doing is, how to work it, etc. but why no constructor(), no new, no class, no etc.prototype.etc pattern? I know i'm creating an object, calling a method existing Within the object, etc. I believe i'm beginning to ramble.
Lo, an example
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
which is || can be instantiated (?) like so:
let aCounter = counterFunction() // where i'm getting tripped up
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
I know this is rambling, but help! I think it will make things click more inside once this lexical puzzle piece is put into position!
That is just a function that returns an object literal, which does not act like a class (doesn't have a prototype, and as you pointed out, does not use new, etc).
The functions that are set as the properties of this object (which you store in aCounter) seem to act like class methods because they keep the reference to the variable val alive, but this is not because val is in any way associated with the actual object.
Instead, those functions are closures that keep the reference to the variable alive for as long as the functions themselves are alive.
So to answer your question, what you have described doesn't have any name in particular. It's just a function that returns an object.
Edit:
You asked why there is no constructor() or related syntax in this pattern. Object literals in JavaScript are just mappings of names and values:
const x = { a: 3, b: "hello" };
You do not need a constructor for this, and there is no prototype because it was not instantiated using a constructor. On the other hand, classes and constructor functions are templates for objects that will be created later, and those objects do have a prototype and a constructor because the template contains logic that initializes the object.
class A
{
constructor()
{
this.a = new Date();
this.b = this.a.toString(); // you cannot do this in an object literal
}
}
const x = new A();
Question:
What is it called when a function behaves like a class but doesn't use the class keyword, nor “new” keyword (in Javascript)?
Answer:
It's called a "factory function".
Factory functions usually return a object of a consistent type but are not instances of the factory function itself. Returned objects would rarely inherit from the factory function's prototype property, and calling the factory function does not require new before the function being called.
What you showed there is nothing special. It is just a normal function that has a closure.
Though, you can call it as a type of design pattern.
It looks similar to Revealing Module Pattern where you can separate public property and private property.
Below is an example (not a good one tho):
var counter = function(){
var privateCount = 0;
var privateHistory = [];
return {
getVal: function(){
return privateCount;
},
increment: function(){
privateCount++;
privateHistory.push('+');
return this.getVal();
},
decrement: function(){
privateCount--;
privateHistory.push('-');
return this.getVal();
},
publicHistory: function(){
return privateHistory;
}
}
}
var aCounter = counter();
console.log(aCounter.increment());
console.log(aCounter.decrement());
console.log(aCounter.publicHistory());
Here, you can't directly manipulate the private variables that I don't expose to you.
You can only manipulate those private variables only if I expose the function to you. In this case, the .increment() and .decrement() function.
As you can see, there is no class, no prototype, no constructor.
I can see how you may get tripped up, let's go through your code and explore what's going on:
const counterFunction = () => {
let val = 0
return {
increment() { val++ },
getVal() { return val }
}
}
At this point counterFunction is a variable that points to a function, it's essentially a function name. The ()=>{...} is the function body or function definition and within it the return statement shows that it returns an unnamed object with two property methods.
let aCounter = counterFunction() // where i'm getting tripped up
This is calling your previously defined function, which again returns the object with two methods and assigns it to the variable aCounter. If you did the same thing again for a variable called bCounter they would hold two independent objects.
and works like
aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2
Because the method inside the object refers to a variable outside the scope of the object, but within the function body, a closure is created so that the state of val may be retained. Because the variable is in use, the browser's cleanup process skips over it, so the function is still kept in memory, I believe until the object is destroyed and the function's variable is no longer used.

Javascript Object : Literal Vs Constructor [duplicate]

This question already has answers here:
Literal notation VS. constructor to create objects in JavaScript [duplicate]
(2 answers)
Closed 9 years ago.
For creating Javascript object, we can use Literal or Constructor way;
In Constructor way, we say;
function myObj(){
this.myProp1 = "abc";
this.myProp2 = "xyz";
}
In literal way, we say;
var myObj = {
myProp1:"abc",
myProp2:"xyz",
}
My question is when declaring properties, why there is a difference like why do we use "this.myProp1" in case of Constructor way and not use "this" in Literal way ?
The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).
There are a few subtleties about the first example to note:
When the code is executed, an anonymous function is created and assigned to myObj, but nothing else happens. methodOne and methodTwo don't exist until myObj is explicitly called.
Depending on how myObj is called, the methods methodOne and methodTwo will end up in different places:
myObj():
Since no context is supplied, the this defaults to window and the methods will become global.
var app1 = new myObj():
Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, myObj.methodOne remains undefined.
myObj.call(yourApp):
This calls my myObj but sets the context to be another object, yourApp. The methods will get assigned to yourApp, overriding any properties of yourApp with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example methodOne and methodTwo rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:
var myObj = function(){
var variableOne = "ABCD1234";
this.methodOne = function(){
// Do something with variableOne
console.log(variableOne);
};
this.methodTwo = function(){
// Do something else with variableOne
};
};
myObj();
alert(variableOne); // undefined
alert(myObj.variableOne); // undefined
If you wanted to make variableOne exposed (public) you'd do:
var myObj = function(){
this.variableOne = "ABCD1234";
this.methodOne = function(){
// Do something with variableOne
console.log(this.variableOne);
};
this.methodTwo = function(){
// Do something else with variableOne
};
};
myObj();
alert(variableOne); // undefined
alert(myObj.variableOne); // ABCD1234
When defining something literally, the object is being built directly in the code. It doesn't exist yet until it is complete. At that point, this would have no meaning (not that there is any need for it either).
To understand this in the object creation function, first realize that this is special in JavaScript. Whenever you call a function, you can pass anything you want to be this. In general, things like event handlers will pass the event-causing DOM object to be passed as this. In your code, you do this as: MyFunction.call(whatever_needs_to_be_this[, param0, param1]);. When you use the new operator, such as var mything = new SomeThing();, JavaScript is essentially doing something like:
var mything = {};
SomeThing.call(mything);
this in this case is going to be mything in your function.

How do I inherit a function from a base object and overwrite it in javascript

What I am trying to do is have a child object provide its own implementation for a function defined in a base object. As far as I've understood so far prototypes are the best (only!) way to go about doing this.
Note also that I am currently developing using the game engine: Turbulenz and as such I am trying to follow / stick to their style as closely as possible. In the engine "classes"/objects are defined and created in the following manner
function baseObject() { }
baseObject.prototype =
{
myMember1: 1,
myMember2: 2,
myMethod: function myMethodFn() {
return this.myMember1 + this.myMember2;
}
}
baseObject.Create = function baseObjectCreateFn
{
var o = new baseObject();
return o;
}
This would allow me to do the following
var anObject = baseObject.Create();
var someValue = anObject.myMethod(); // should return 3
What I would like to be able to do now is to create a new object that inherits all the properties of baseObject while allowing me to overwrite its myMethod function to for example subtract the two member values instead of add.
Would I be correct in saying that I will have to create another object then alter its prototype? The part thats throwing me most is that the definition of the baseObject's prototype is defined as an object literal and so I'm unsure of the syntax to overwrite one of its members, i.e. would the following be valid or not? :
function childObject() {}
childObject.prototype = baseObject.Create() // would this inherit from baseObject?
// or should it be: childObject.prototype = new baseObject();
// this is the part thats confusing me as the syntax
// doesn't quite match the original base objects prototype
// syntax and I'm unsure if that will matter
childObject.prototype.myMethod = function myMethodFn() {
return this.myMember1 - this.myMember2;
}
childObject.Create = function childObjectCreateFn
{
var o = new childObject();
return o;
}
var aChildObject = childObject.Create()
var anotherValue = aChildObject.myMethod() // would this return -1 as expected?
To summarise I'm trying to create an object that will overwrite a function that exists in a base object by inheriting the function from the base object and changing it, how do I do this? Thanks for your time.
You have it correct.
As for the syntax confusion, there is no real difference between
thing.prototype.myMethod = function () { ... }
and
thing.prototype = { myMethod: function() { ... } };
except for the fact that in the second one you are setting the prototype all at once (to an object literal), and if you do it again, you'll overwrite the prototype all at once with a new object literal. But because it is an object literal, you can't do inheritance this way (everything declared with naked braces { ... } is just an instance of Object of no special type). If you stick with the first syntax you'll always be ok.
Note that when you put:
childObject.prototype.myMethod = function myMethodFn() { ... }
The part where you put myMethodFn is actually ignored. The function is named myMethod by the fact that this is where you assigned it.
Similarly, where you have
childObject.Create = function childObjectCreateFn
you don't need childObjectCreateFn (it's ignored), and you need to put parentheses () somewhere after function or it's a syntax error.
Moving on to the reason why this works, every created object in Javascript has a prototype. When you call a method on that object, it first looks inside the object itself to see if a key corresponding to the name of the method exists. If not, it looks in the prototype object for the same thing, and if it's not there, it goes to that object's prototype, and so on, until it gets to the root Object, which has no prototype.
In this way you can override an implementation merely by naming it the same thing, but having it appear earlier in the prototype chain. That's exactly what you're doing on childObject. It retains the functionality of baseObject because you created an instance of baseObject to serve as childObject's prototype. Then you augmented childObject's prototype with a new method of the same name, but one that comes earlier in the prototype chain.

Is "this" necessary in javascript apart from variable definition

My question is dead simple.
I just casually discovered that once you have defined a property with this. into an object, you don't need to prepend this. anymore when you want to call them.
So this. is really meant to be used ad definition time, like var?
I found it my self shortly after, i was referencing the window object with this. since i called my object without using new, so like it was a function.
One extra question, maybe for comments. Inside the main object, if i create a new object, and use this during the object definition, this this what will be referring to?
No, unless the context of this is a global object, such as window. Take the following example:
function Foo(bar) {
this.data = bar;
console.log(this.data); // OK
console.log(data); // ReferenceError
}
In this example, you'll get a ReferenceError: data is not defined on the first console.log(data), unless, data is a global variable. To access the instance's public member, you have to use this.data.
References:
Understanding JavaScript’s this keyword
The this keyword
There are all sorts of circumstances where you MUST use this in order to reference the right data.
These two implementations do very different things:
Array.prototype.truncate(newLen) {
// sets the length property on the current Array object
this.length = newLen;
}
Array.prototype.truncate(newLen) {
// sets a global variable named length
length = newLen;
}
var arr = [1,2,3,4,5,6,7];
arr.truncate(2);
You MUST use this in order to control what happens if you want to modify the current object. Your assumption that you can leave it off and it will still modify the current object's properties is not correct. If you leave it off, you are modifying global variables, not member properties.
So this. is really meant to be used ad definition time, like var?
No, the point of this is to be the current scope of execution. You can (and will) run into weird errors if you don't use this. For example, imagine you are an object with a property val and then on the prototype of that object you have
App.obj = function(){
this.val = 'initial';
}
obj.prototype.myMethod = function(val) {
// how would you assign argument val to object val?
}
also note that your reasoning breaks down with methods.
obj.prototype.meth2 = function(){
myMethod(); // fails where this.myMethod() would work.
}
See http://jsfiddle.net/BRsqH/:
function f(){
this.public='hello!';
var hidden='TOP SECRET!';
}
var instance=new f();
alert('Public data: '+instance.public+ /* gives "hello!" */
'\nHidden data: '+instance.hidden /* gives undefined */
);
Variables created with var are hidden and cannot be viewed nor modified outside the function which created them.
But variables created with this are public, so you can access them outside the function.
I think I got it.
I defined my object as function My_Object(){...} and then called it with MyObject(). This way the My_Object was treated as a function, not an object and therefore this == window.
So in the end I was attaching properties and methods to window instead of My_Object! That's way there were available without prepending .this.
The right way to initialize My_Object as an object is to call it like this new My_Object, isn't right?

What is the difference between myObject.someFunc = function(){...}; or myObject.prototype.someFunc = function(){...} in javascript? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Prototyped and a non-prototyped method? [duplicate]
(1 answer)
Closed 8 years ago.
Suppose I create an object in javascript.
var myObject = {};
What is the difference between...
myObject.someFunc = function(){...};
and
myObject.prototype.someFunc = function(){...}
in javascript?
I am having trouble understanding the difference or if there is a difference and how and when to use either of these syntaxes.
It seems when I code something like this that there really is no difference.
I am looking for both a client side (browser) and server side (like node.js) answers.
I want to code properly and accurately and this is really bothering me.
In this case:
var myObject = {};
myObject.someFunc = function(){...};
All you're doing is creating a plain object, which happens to have a property which is a reference to a function. This is often done just for name spacing, i.e. to group a whole load of functions in one place under a common object.
Note however that var myObject = {} doesn't actually have a prototype so your second example is impossible.
For an object to have a prototype it must be the result of a constructor function, i.e.
function MyObject() {
...
}
MyObject.prototype.someFunc = function() { }
var myObject = new MyObject();
// myObject.someFunc can now be used
The prototype is a property of the constructor function - not of any instance of that class.
If you put the function on the prototype only one instance of the function object exists and will be shared by all instances of the class. This is more memory efficient that having a copy on each instance.
All of this applies regardless of whether the code is in a browser or on a server - it's still the same language.
Essentially this represents a static method (or a method attached to only that object (myObject in this case):
myObject.someFunc = function () {...};
This represents a method attached to the prototype of the object (an instance method):
myObject.prototype.someFunc = function () {...};
myObject.someFunc = function(){...} is a one time instance of that function, who's return value is being assigned to the someFunc property of myObject.
myObject.prototype.someFunc = function(){} is actually creating a method that can be called anywhere on myObject and will change the same instances of values each time.
myObject.prototype.someFunc = function(num){
this.num_to_be_stored = num;
}
will change the value of num_to_be_stored not someFunc which is what is happening in the first instance.
edit: sorry early morning was not clear on what I was trying to say.

Categories

Resources