Understanding this object in JS [duplicate] - javascript

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 6 years ago.
I am new to JS and like other novice struggling to understand concept of THIS keyword in JS. In below snippet name is changed to value1 which I understand since its c object which is calling log function .
But not able to understand why setName function is not able to change value of name variable?
var c ={
name:"value",
log:function(){
this.name="Value 1";
console.log(this.name); // c object is invoking log function hence this refers to c obj
var setName= function(newName){
this.name=newName;
}
setName('Value 2'); // isn't log function calling setName
console.log(this.name);
}
}
c.log();

Value of this is determined by how function is called.
setName is not having context of c object, it is having the global(window) context. Use Function#bind to specify that context.
var c = {
name: "value",
log: function() {
this.name = "Value 1";
console.log(this.name);
var setName = function(newName) {
this.name = newName;
}.bind(this);
setName('Value 2');
console.log(this.name);
}
};
c.log();

This line:
var setName= function(newName){
this.name=newName;
}
Will not neccessary reference the upper function, since your call to it was direct and the dunction is not a direct member of the upper function, something like: this.setName = function()....
So it will refer to a new context.
To change the upper one you have to make another reference for it not using this, like:
var upperThis = this;
var setName= function(newName){
upperThis.name=newName;
}

The function setName creates a new context, so it creates a new this.
This would do the trick:
var that = this;
var setName= function(newName){
that.name=newName;
}

Related

javascript - why is 'this' not referencing the object? code below [duplicate]

This question already has answers here:
How do JavaScript closures work?
(86 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
I don't understand why this.name isn't the same as obj.name, basically why in this case this refers to the window object and not the obj object. In the code below, this.name is instantiated after obj.name..
function createNewPerson(name) {
var obj = {};
obj.name = name;
alert(this.name);
return obj;
}
Per MDN:
Inside a function, the value of this depends on how the function is
called. Since the following code is not in strict mode, and because
the value of this is not set by the call, this will default to the
global object , which is window in a browser.
So in your case you have this as the Window object, not the obj. You may get the obj context inside your function via binding it manually, for example:
function createNewPerson(name) {
console.log(this.name); // Hello
console.log(name); // World
}
var obj = {};
obj.name = 'Hello';
var salva = createNewPerson.apply(obj, ['World']);
But what you really need, as I can understand, is a function cunstructor and instantiating an object via new operator:
function createNewPerson(name) {
this.name = name;
}
var salva = new createNewPerson('Salva');
console.log(salva.name); // Salva

How do I reference class variables/methods from nested functions? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
class Foo {
constructor() {
this.foobar = "foobar";
}
bar() {
let _this = this;
return function() {
try {
alert("Attempt 1: "+foobar);//ReferenceError: foobar is not defined
myMethod();
} catch(err) {console.log(err);}
try {
alert("Attempt 2: "+this.foobar);//TypeError: this is undefined
this.myMethod();
} catch(err) {console.log(err);}
try{
alert("Attempt 3: "+_this.foobar);//Works!
_this.myMethod();
} catch(err) {console.log(err);}
}();
}
myMethod() {
alert("myMethod()");
}
}
new Foo().bar();
The above example is very simplified - the anonymous function inside bar() was a jQuery call originally, but for the sake of the question I didn't include that.
Why don't attempts 1 and 2 work? Do I have to use the _this trick to reference class variables/methods? How do I reference class variables/methods from nested functions?
Are you familiar with how the this keyword works in JavaScript? It's value will depend on how the function is called, not in how it is defined. For example, if you do the following:
var dog = {
greeting:"woof",
talk:function (){
console.log(this.greeting);
}
};
var cat={
greeting:"meow",
talk:dog.talk
};
dog.talk();
cat.talk();
You will see that when the talk function is called as a method of an object, that object will be used as the value of this.
The same happens with ES6 classes, where class methods are still JavaScript functions and the rules for deciding the value of this still apply. If you want to avoid declaring an auxiliar variable, you should look into using bind:
var mammal = {
greeting:"<noise>",
getTalk:function (){
return function(){
console.log(this.greeting);
};
},
getTalkBinded:function (){
return (function(){
console.log(this.greeting)
}).bind(this);
}
};
var dog={
greeting:"woof",
talk:mammal.getTalk(),
talkBinded:mammal.getTalkBinded()
};
var cat={
greeting:"meow",
talk:mammal.getTalk(),
talkBinded:mammal.getTalkBinded()
};
dog.talk();
cat.talk();
dog.talkBinded();
cat.talkBinded();
You are returning self-execution function execution result and during that function execution this it global context(not your class object). to make it work use () => {}() arrow function call syntax, as it captures current context, or function() { }.bind(this)().
See this simple example,
function a(){
this.someProp = 5;
console.log(this);
var _this = this; //so we explicitly store the value of `this` to use in a nested function
return function(){
//value of `this` will change inside this function
this.anotherProp = 6;
console.log(this);
//to use the methods and props of original function use `_this`
console.log(_this)
}
}
var c = a.call({}) //prints {someProp: 5}
c.call({}) //prints {anotherProps: 6} {someProp: 5}

Trying to understand scoping within two short JavaScript functions

What is the difference between the following two JavaScript functions? I know variables declared with var are local inside the function, and if declared withthis` keyword are exposed to outer word. is there any other difference between
function student(param1, param2, param3) {
this.name = param1;
this.age = param2;
this.address = param3;
}
and
function student(param1, param2, param3) {
var name = param1;
var age = param2;
var address = param3;
}
Short answer: You would use the first one for a constructor. The second function does nothing. If you want to use 'private variables', refer to functional scoped variables in the contstructor by instance methods via a closure.
This function would be used the following way to create a student. The parameters passed in are assigned to the newly create student object.
function student(param1, param2, param3){
this.name = param1;
this.age = param2;
this.address = param3;
}
var student1 = new student('steve', 22,'333 E 3rd Ave');
var student2 = new student('rachel', 34,'111 N 1st St');
console.log(student1.name); // 'steve'
console.log(student2.name); // 'rachel'
The second one wouldn't satisfy for a constructor.
It declares variables with functional scope that remain unused. Once the execution of the student function ends, the 3 variables defined within will be garbage collected. This function doesnt seem to accomplish anything.
What do you expect this function to do? It can't be used the same way:
function student(param1, param2, param3){
var name = param1;
var age = param2;
var address = param3;
}
var badStudent = new student('Greg', 22,'222 W 2nd Rd');
console.log(badStudent.name); // undefined
Edit
Someone brought up how to make 'private member variables' using variables declared with var inside a constructor. Use closures:
function student(param1, param2, param3) {
var name = param1;
var age = param2;
var address = param3;
this.getName = function(newName) {
if (newName)
name = newName;
return name;
};
}
var myStudent = new student('steve', 22,'333 E 3rd Ave');
console.log(myStudent.name);
console.log(myStudent.getName());
console.log(myStudent.getName('dan'));
console.log(myStudent.getName());
Note that because the instance method getName refers to a functional scoped variable declared in the constructor, a closure remains that has references those variables. Because of the closure there are still references to the variables once the constructor ends, and they are not garbage collected. Thus via the instance method, you can get and set this variable which cannot be accessed via the resulting object of the constructor.
Basic difference between this. vs var variables is the scope. Variables declared as a part of this will be part of objects and variables declared with var might be private. Might because, it depends on your return. If you do not use return, then they will be private
Sample
function Student(fname, lname, dob) {
var _fname = fname,
_lname = lname,
_dob = new Date(dob);
this.fullName = _fname + " " + _lname;
this.age = (new Date()).getFullYear() - _dob.getFullYear();
}
var stu = new Student('foo', 'bar', '1998/11/13');
console.log(stu);
console.log(stu._fname)
As you see, _fname is passed and was stored using var. So its scope is till function only. So when you try to access it outside function, it is not available.
So in simple, you can use this to define public properties and use var to define private ones.
In JavaScript for creating object we use 'function' as constructor, this constructor functions basically return an object .
when you declare variable with 'var' instants of 'this.var name' , in this case mean you try using those variable to create an object .those variable declared with 'var' just are local variable inside function.
on other hand , when you use 'this.variableName' you create a property for object that constructor function try to create it .
'this.' refer to object that constructor function create.
'var variableName' is just a local variable and it is not a property of 'this' object.
function student(param1,param2,param3){
this.name=param1;
this.age=param2;
this.address=param3;
}
var t=new student('farhad',28,'address');
will create this object:
t{
name:'farhad',
age:28,
address:'address'
}
and
function student2(param1,param2,param3){
var name=param1;
var age=param2;
var address=param3;
}
var t2=new student2('farhad',28,'address');
will create this object:
t2{
}
in 't2' you don't see any property
this is used inside a function and it contains the value of the object that invokes function
Here this refers to the instance of the object & is not assigned a value until an object invokes the function where it is defined
function Student(param1, param2, param3) {
this.name = param1;
this.age = param2;
this.address = param3;
this.print = function() {
console.log(this.name + this.age + this.address)
}
}
var stud = new Student('a', 'b', 'c');
stud.print(); // abc
In the later case var name=param1;var age=param2;var address=param3; you are assigning each of the parameters to a variable and this variables have scope only inside the function

prototype printing undefined in console with setInterval function in javascript [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 6 years ago.
I am trying to print something in prototype function using setInterval it's showing undefined in console.
function newFunc(){
this.name = "this is person name";
this.Age = "16 Years";
}
newFunc.prototype.init = function(){
setInterval(function(){newFunc.prototype.xyz()}, 1000);
}
newFunc.prototype.xyz = function(){
console.log(this.Age);
}
var abc = new newFunc();
abc.init();
newFunc.prototype.init = function(){
this.xyz();
}
Change to this.xyz(), as you are in the same instance. It won't work in setInterval because this is lost here. You need to have a reference of this.
newFunc.prototype.init = function(){
var that = this;
setInterval(function(){that.xyz()}, 1000);
}
A Working fiddle:
https://jsfiddle.net/ptvckunk/
Its also inside the function.so apply with this.xyz() .this declare with some variable and apply into the setInterval(copy.xyz())
Why use this
this.xyz() only applicable on newFunc.prototype.init.Not ah setInteval(function (){}).These Two function are seperate. so to passing with setInterval function .We need one variable.So only i was declare with var copy
function newFunc(){
this.name = "this is person name";
this.Age = "16 Years";
}
newFunc.prototype.init = function(){
var copy = this;//in `this` applicable only newFunc.prototype.init.it copy from another variable
setInterval(function(){//in this function are different.
copy.xyz()//passing variable and excute the function
}, 1000);
}
newFunc.prototype.xyz = function(){
console.log(this.Age);
}
var abc = new newFunc();
abc.init();

How to access class variables from inner prototype - javascript [duplicate]

This question already has answers here:
'this' in function inside prototype function [duplicate]
(8 answers)
Closed 7 years ago.
I might not be clear with my title of the question. Sorry for that.
Here is what I wanted to do.
I'm trying to use prototyping pattern in javascript. I created a class as following.
var MyClass = null;
(function() {
MyClass = function() {
this.clsVar = "I'm inside constructor";
};
MyClass.prototype = {
constructor: MyClass,
myFunc1: function() {
console.log("I'm func1 accessing constructor variable : " + this.clsVar);
},
nested: {
myFunc2: function() {
console.log("I'm func2 accessing constructor variable : " + this.clsVar); // I know, this will never point to the class scope
}
}
}
}())
I'm creating an object.
var my = new MyClass();
my.myFunc1(); // which prints "I'm func1 accessing constructor variable : I'm inside constructor"
my.nested.myFunc1(); // as expected, it prints "I'm func2 accessing constructor variable : undefined
All I am trying to do is, I should be able to access clsVar from nested.myFunc2
is that possible.? Any help is greatly appreciated and needed.
Thanks.
Actually, there is a point.
The this inside your myFunc2 does not refer anymore to MyClass but to another context. So, the fastest way is to do is to use call or apply like:
var myNewObject = new MyClass();
myNewObject.nested.myFunc2.call(myNewObject, arg1, arg2);
or
myNewObject.nested.myFunc2.apply(myNewObject, [arg1, arg2]);
JavaScript's prototype-based class system does not allow this.
MyClass's prototype will be shared between all instances of the class. In the following code, both instances will use the same function instance...
var first = new MyClass(), second = new MyClass();
first.nested.myFunc2(); <-- Same prototype function
seecond.nested.myFunc2(); <-- Same prototype function
When the code enters the "myFunc2" definition, which parent should it be accessing?
If you need access to the parent's "this" value, you'll have to use a closure and set up the nested object in the parent constructor as below.
var MyClass = null;
(function() {
MyClass = function() {
this.clsVar = "I'm inside constructor";
var that = this;
this.nested = {
myFunc2: function() {
console.log("I'm func2 accessing constructor variable : " + that.clsVar); // I know, this will never point to the class scope
}
}
};
MyClass.prototype = {
constructor: MyClass,
myFunc1: function() {
console.log("I'm func1 accessing constructor variable : " + this.clsVar);
}
}
}())

Categories