This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
In the following example there is a simple object. Two instances were created for me to test variable scope.
When test1a (and test2a) is assigned to the method ShowNum it behaves identically as when calling oneObj.ShowNum() by itself. However, when test1b is assigned to the method ShowNum2, then it behaves differently than calling oneObj.ShowNum2() directly.
This is a little puzzling to me because it seems that the 'this' scope is being lost during assignment, but at the same time it is NOT lost because 'num' is still found (and num is as unique to the object instance as this.num2 is).
What is the esoteric explanation for this behavior ?
function TestObject ()
{
var num = 25;
this.num2 = 50;
this.ShowNum = function () {return num;}
this.ShowNum2 = function () {return this.num2;}
this.SetNum = function (newnum) {num = newnum;}
}
var oneObj = new TestObject();
var twoObj = new TestObject(); twoObj.SetNum(100); twoObj.num2 = -12;
var test1a = oneObj.ShowNum;
var test1b = oneObj.ShowNum2;
var test2a = twoObj.ShowNum;
var test2b = twoObj.ShowNum2;
console.log(oneObj.ShowNum());
console.log(oneObj.ShowNum2());
console.log(test1a());
console.log(test1b());
console.log(twoObj.ShowNum());
console.log(twoObj.ShowNum2());
console.log(test2a());
console.log(test2b());
Result:
25
50
25
undefined
100
-12
100
undefined
EDIT:
This question does seem like a variant of the one -->here as pointed out by the replies.
My instinctive expectation was that var test1b = oneObj.ShowNum; should imply
var test1b = oneObj.ShowNum2.bind(oneObj); making it for consistent behavior across languages (as Mahesha999 mentioned with the following)
The this keyword behaves differently in JavaScript compared to other
language. In Object Oriented languages, the this keyword refers to the
current instance of the class. In JavaScript the value of this is
determined mostly by the invocation context of function
(context.function()) and where it is called.
Right now I don't feel like pressing further and I consider this matter closed.
Reason :
// you are not assigning the whole object , but just passing refernce to the function
var test1a = oneObj.ShowNum;
var test1b = oneObj.ShowNum2; // so from here it will lose the context of this
test1a is like
function () {return num;}
and test1b is like
function () {return this.num2;}
Here, if you directly assign the function, here this is not pointing to parent function anymore. as you have just assigned the function
You can check that by just putting console.log inside like,
this.ShowNum2 = function () { console.log(this); return this.num2;}
Debugging : Run the below code snippet and you will get idea :
function TestObject ()
{
var num = 25;
this.num2 = 50;
this.ShowNum = function () {return num;}
this.ShowNum2 = function () { console.log(this); return this.num2;}
this.SetNum = function (newnum) {num = newnum;}
}
var oneObj = new TestObject();
var twoObj = new TestObject(); twoObj.SetNum(100); twoObj.num2 = -12;
var test1a = oneObj.ShowNum;
var test1b = oneObj.ShowNum2;
var test2a = twoObj.ShowNum;
var test2b = twoObj.ShowNum2;
console.log(oneObj.ShowNum());
console.log(oneObj.ShowNum2());
console.log(test1a());
console.log(test1b());
console.log(twoObj.ShowNum());
console.log(twoObj.ShowNum2());
console.log(test2a());
console.log(test2b());
Solution :
//.bind(parent_object);
var test1b = oneObj.ShowNum2.bind(oneObj);
var test2b = twoObj.ShowNum2.bind(twoObj);
function TestObject ()
{
var num = 25;
this.num2 = 50;
this.ShowNum = function () {return num;}
this.ShowNum2 = function () {return this.num2;}
this.SetNum = function (newnum) {num = newnum;}
}
var oneObj = new TestObject();
var twoObj = new TestObject(); twoObj.SetNum(100); twoObj.num2 = -12;
var test1a = oneObj.ShowNum;
var test1b = oneObj.ShowNum2.bind(oneObj);
var test2a = twoObj.ShowNum;
var test2b = twoObj.ShowNum2.bind(twoObj);
console.log(oneObj.ShowNum());
console.log(oneObj.ShowNum2());
console.log(test1a());
console.log(test1b());
console.log(twoObj.ShowNum());
console.log(twoObj.ShowNum2());
console.log(test2a());
console.log(test2b());
Related
This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 2 years ago.
This is what I have attempted, and may give a better gist of the question I'm trying to ask:
var x = "run";
var y = "Function";
var xy = x + y;
function runFunction() {
console.log("Function has been called.");
}
xy();
What am I doing wrong here?
You could use eval(), but don't. Instead, store your functions in an object:
const functions = {
greetingOne: () => console.log("Hello!"),
anotherGreeting: () => console.log("Hi there!");
};
const f = "greetingOne";
functions[f]();
It is possible if the function lives on an object.
const obj = {
runFunction: function() {console.log('hello')}
}
var x = "run";
var y = "Function";
var xy = x + y;
obj[xy]();
You can call eval that run string as Javascript code
function runFunction() {
console.log("Function has been called.");
}
functionName = 'runFunction'
eval(functionName + '()');
All global functions stores in window object.
let first = "first";
let second = "Second";
let xy = first+second;
function firstSecond() {
return "Hello World";
}
console.log(window[xy]());
let's say you have the following Javascript code:
function random() {
var number = (Math.floor(Math.random() * 2));
document.getElementById('number').innerHTML = number;
return number;
};
function searchE(number) {
var english = englishID[number];
document.getElementById('english').innerHTML = english;
};
function searchJ(number) {
var root = root[number];
var masu = masu[number];
var te = te[number];
document.getElementById('root').innerHTML = root;
document.getElementById('masu').innerHTML = masu;
document.getElementById('te').innerHTML = te;
};
function process() {
var number = random();
searchE(number);
searchJ(number);
};
My problem is when the code is that only the random number and the searchE() results are outputted. I believe the problem is that I'm either not doing var result = moof() correctly or not returning a result from moofproperly.
Can somebody please tell me how to make it work? Thank you for your time.
The problem is that here:
function searchJ(number) {
var root = root[number];
var masu = masu[number];
var te = te[number];
vars get hoisted, so to the interpreter, it looks like:
function searchJ(number) {
var root;
var masu;
var te;
root = root[number];
masu = masu[number];
te = te[number];
So when you try to access those arrays/objects in the outer scope (I'm assuming those variables exist in the outer scope, right?), you're actually referencing the currently undefined variables in the inner scope. Use variable names different from the ones used in the outer scope:
function searchJ(number) {
var foundRoot = root[number];
var foundMasu = masu[number];
var foundTe = te[number];
I have this closure :
function CFetchNextData(ofs, pag, fetchFunction) {
var offset = ofs;
var limit = pag;
return function(options, cb) {
//do stuff to create params
fetchFunction(params, cb);
offset += limit;
};
}
I then create a variable this way:
var fetchInfo = CFetchNextData(0, 10, specificFetchFunction);
fetchInfo(options, myCB);
So that everytime I call fetchInfo, pagination is automatically set to the next set of data. That works great, althought
I'd like to have multiple instance of : "fetchInfo", each one having its own scope.
var A = fetchInfo; // I'd like a clone with its own scope, not a copy
var B = fetchInfo; // I'd like a clone with its own scope, not a copy
I could do:
var A = new CFetchNextData(ofs, pag, fetchFunction);
var B = new CFetchNextData(ofs, pag, fetchFunction);
But obviously I would have to setup "ofs" and "pag" each time, whereas by cloning fetchInfo, I'd have a stable pagination, set only once and for good.
Do you know how to achieve that ?
Thanks in advance
There isn't a concept of cloning a function in JavaScript. You need to call CFetchNextData (or another function) multiple times if you want to create multiple closures.
You could have CFetchNextData return a factory function instead of returning the actual function. But I'm not sure that's really an improvement.
function CFetchNextDataFactory(ofs, pag, fetchFunction) {
return function() {
var offset = ofs;
var limit = pag;
return function(options, cb) {
//do stuff to create params
fetchFunction(params, cb);
offset += limit;
};
};
}
var fetchInfoFactory = CFetchNextData(0, 10, specificFetchFunction);
var A = fetchInfoFactory();
var B = fetchInfoFactory();
This may not answer all of your question but just to pitch in , you could try assigning your parameters to a default / fallback value which will allow you to avoid setting ofs and pag each declaration . Below is a prototype of what I came up with . Its using oop :
class CFetchNextData {
constructor(ofs, pag){
this.OFS = 1; //default value
this.PAG = 10; //default value
this.ofs = ofs;
this.pag = pag;
if(ofs == null || ofs == undefined){
this.ofs = this.OFS;
}
if(pag = null || pag == undefined){
this.pag = this.PAG;
}
}
fetchInfo(){
var data = this.ofs += this.pag;
return data;
}
}
var task1 = new CFetchNextData(); // Falls back to default values..
var task2 = new CFetchNextData(32,31); // Uses values from specified in args...
document.write(task1.fetchInfo() + "\n")
document.write(task2.fetchInfo())
Hope this helps...
This question already has answers here:
Javascript: Do I need to put this.var for every variable in an object?
(6 answers)
Closed 7 years ago.
Why isn't this code working? I'm trying to use the method to add up the properties and then assign the added up properties to its own value.
function howLongILivedSomewhere(college, home1, home2) {
this.birthHome = 18;
this.college = college;
this.home1 = home1;
this.home2 = home2;
this.calcYearsAlive = function() {
return birthHome + college + home1 +home2;
};
this.yearsAlive = calcYearsAlive();
}
var me = new howLongILivedSomewhere(4, 2, 3);
console.log(me);
You missed this keyword during your method / property call. Try like below.
function howLongILivedSomewhere(college, home1, home2) {
this.birthHome = 18;
this.college = college;
this.home1 = home1;
this.home2 = home2;
this.calcYearsAlive = function() {
return this.birthHome + this.college + this.home1 + this.home2;
};
this.yearsAlive = this.calcYearsAlive();
}
var me = new howLongILivedSomewhere(4, 2, 3);
console.log(me.yearsAlive); // output: 27
What is this keyword?
A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
How does "this" keyword work within a function?
Update the constructor to:
function howLongILivedSomewhere(college, home1, home2) {
this.birthHome = 18;
this.college = college;
this.home1 = home1;
this.home2 = home2;
this.calcYearsAlive = function() {
return this.birthHome + this.college + this.home1 + this.home2;
};
this.yearsAlive = this.calcYearsAlive();
}
var me = new howLongILivedSomewhere(4, 2, 3);
console.log(me);
Use this keyword when you need to access the object properties (see here more details).
Suppose we define a function that simply increments its input by some stored value dd:
var obj={}
obj.dd=1
obj.f=function(x){
return x+this.dd
}
Alternatively you could create a closure for dd as follows but this would create a static increment as opposed to one that could be altered later:
var dd=1
var f=function(x){
return x+dd
}
We could alternatively store dd in the function itself:
var obj={}
obj.f=function(x){
return x+this.f.dd
}
obj.f.dd=1
I am curious as to whether it is possible for a function to retrieve a variable attached to itself without going through a parent object, something like a self keyword that would refer to the function itself and would allow the following:
var f=function(x){
return x+self.dd
}
f.dd=1
I know it is unnecessary to do such a thing but I think it would be cool if you could.
You can give function literals a name:
var f = function me(x) {
return x + me.dd;
};
f.dd = 1;
This doesn’t work properly in older versions of IE/JScript, though, as me and f don’t reference the same object. The (deprecated and not usable in strict mode) alternative is arguments.callee:
var f = function(x) {
return x + arguments.callee.dd;
};
f.dd = 1;
Also, your note about the closure isn’t quite right; it can be altered later, even through another function:
var dd = 1;
var f = function(x) {
return x + dd;
};
var setdd = function(_dd) {
dd = _dd;
};
A function is an object. If you reference the var holding the function:
var f = function (x) {
return x + f.dd
};
f.dd = 1;
alert(f(1));
result: 2
If the function is named, you can do the same:
function foo(x) {
return x + foo.dd;
}
foo.dd = 1;
alert(foo(1));
result: 2