I am new to Javascript. I am trying to understand where "this" is bound to using different examples. I am using console.log to print some values as shown below.
function FuncObject(value) {
this.answer = value;
this.get_answer = function () {
return this.answer;
}
};
var f = new FuncObject(42);
var fanswer = f.get_answer;
console.log(fanswer())
console.log prints "function" instead of "undefined". document.writeln seems to print "undefined" which is the right one because this is bound to the window object which does not have answer. Now printing function confuses me. Now I am wondering what i should be using for logging. I am unable to find an explanation for this.
thanks mohan
Just incase you didn't notice, there's a typo in your posted code of
this.get_answer = funcition ()
With that in mind, I'm not entirely sure of your experience level so let me cover all the bases.
function FuncObject(value) {
this.answer = value;
this.get_answer = function () {
return this.answer;
}
};
var f = new FuncObject(42);
var fanswer = f.get_answer;
console.log(fanswer())
You're setting fanswer = f.get_answer where f.get_answer is a function, so as such it sets fanswer to the function equivalent of this.get_answer.
If you want the return value of f.get_answer you need to call f.get_answer(), which returns 42.
With what you put, console.log(fanswer()) does print undefined as expected.
If you simply do console.log(fanswer) it records it as function, also as expected.
I'm not sure why you would receive function as you stated in your question, because I definitely do not, jsbin.
Related
CLOSURES IN JAVASCRIPT
Hi there,
I am facing some struggles with my javascript code, maybe you can help with the issue about closures.
this is my code:
function seatReservation(aSeat) {
let secret = aSeat;
return function (){
return secret;
}
};
class Reservations {
#aMailadress;
#mySeatList;
constructor(aMailadress){
this.#aMailadress = aMailadress;
this.#mySeatList = [];
}
addSeatReservation(aSeat){
this.#mySeatList.push(aSeat);
}
printReservations(){
this.#mySeatList.forEach(seat => {
console.log(seat);
});
}
};
// Test
const list = new Reservations('peter#mail.com');
list.addSeatReservation(new seatReservation('D3'));
list.addSeatReservation(new seatReservation('F6'));
list.printReservations();
the output in the console is:
[(Anonymous function)]
[(Anonymous function)]
Expected output:
D3
F6
Who can help?
Thanks
The new seatReservation('D3') creates a function which will, when called, return the secret passed to it. You could for example do: console.log(seat());. You call the function, thus retrieving the data from the closure.
The variable i am using becomes undefined after a certain point. Can someone help me in understanding what is happening.
The below code is a protractor code.
this.searchBy = element(by.model('searchCompanyComponent.searchByValue'));
this.clickTheProvidedValueInSearchByDropdown = function (selectedItem) {
var x = this.searchBy;
this.searchBy.all(by.tagName('option')).filter(function (elem, index) {
return elem.getText().then(function (text) {
return text.toUpperCase().replace(/ |-/g, '') === selectedItem.toUpperCase().replace(/ |-/g, '');
});
}).getText().then(function (text) {
console.info(x); // 1
console.log(this.searchBy); // 2
});
};
console.log(this.searchBy); //3
The console log at 1 and 3 shows the locator object, but console log at 2 shows as undefined.
What is the reason behind this unexpected behavior?
In JavaScript, this can mean a lot of different things depending on the context in which you are referencing it.
When you are saying console.log(this.searchBy); // 2 you are in the context of the anonymous function you passed to getText, which has no searchBy property. You will either need to bind this function to the context of your page object or use the stored reference to searchBy in x
It may be helpful to review this mdn article
By Pure, I mean in the sense of the λ-calculus, i.e., a single-argument function containing nothing on its body other than single-argument functions and single argument function calls. By recovering the source code, I mean up to variable renaming. So, for example,
n2 = function(v0){return function(v1){return v0(v0(v1))}}
console.log(source(n2));
console.log(source(n2(n2)));
Should print:
function(v0){return function(v0){return v0(v0(v1))}}
function(v0){return function(v0){return v0(v0(v0(v0(v1))))}}
That is, the first line shows the original source of the function n2, and the second one shows the source of the function that is returned by the evaluation of n2(n2).
I've managed to implement it as follows:
function source(f){
var nextVarId = 0;
return (function recur(f){
if (typeof f === "function"){
if (f.isVarFunc) return f(null);
else {
var varName = "v"+(nextVarId++);
var varFunc = function rec(res){
var varFunc = function(arg){
return arg === null
? "("+res.join(")(")+")"
: rec(res.concat(recur(arg)));
};
varFunc.isVarFunc = true;
return varFunc;
};
varFunc.isVarFunc = true;
var body = f(varFunc([varName]));
body = body.isVarFunc ? body(null) : recur(body);
return "(function("+varName+"){return "+body+"})";
};
} else return f;
})(f);
};
The issue is that I'm using some rather ugly method of tagging functions by setting their names to a specific value, and that it won't work in functions that are applied more than once (such as a(b)(b)). Is there any better principled way to solve this problem?
Edit: I managed to design a version that seems to be correct in all cases, but it is still an ugly unreadable unprincipled mess.
Finally, this is a considerably cleaned up version of the mess above.
// source :: PureFunction -> String
// Evaluates a pure JavaScript function to normal form and returns the
// source code of the resulting function as a string.
function source(fn){
var nextVarId = 0;
return (function normalize(fn){
// This is responsible for collecting the argument list of a bound
// variable. For example, in `function(x){return x(a)(b)(c)}`, it
// collects `a`, `b`, `c` as the arguments of `x`. For that, it
// creates a variadic argumented function that is applied to many
// arguments, collecting them in a closure, until it is applied to
// `null`. When it is, it returns the JS source string for the
// application of the collected argument list.
function application(argList){
var app = function(arg){
return arg === null
? "("+argList.join(")(")+")"
: application(argList.concat(normalize(arg)));
};
app.isApplication = true;
return app;
};
// If we try to normalize an application, we apply
// it to `null` to stop the argument-collecting.
if (fn.isApplication)
return fn(null);
// Otherwise, it is a JavaScript function. We need to create an
// application for its variable, and call the function on it.
// We then normalize the resulting body and return the JS
// source for the function.
else {
var varName = "v"+(nextVarId++);
var body = normalize(fn(application([varName])));
return "(function("+varName+"){return "+body+"})";
};
})(fn);
};
It is still not perfect but looks much better nether less. It works as expected:
console.log(source(function(a){return function(b){return a(b)}}))
Outputs:
(function(v0){return (function(v1){return (v0)((v1))})})
I wonder how inefficient that is, though.
I have created this:
var where = function(){
sym.getSymbol("Man").getPosition()
}
console.log(where);
if (where()<=0){
var playMan = sym.getSymbol("Man").play();
} else {
var playMan = sym.getSymbol("Man").playReverse();
}
This is for Edge Animate hence all the syms. I am trying to access the timeline of symbol Man, then if it is at 0 play it. But it isnt working and the reason, I think, is that I have an incomplete understanding of how a var works. In my mind I am giving the variable 'where' the value of the timeline position of symbol 'Man'. In reality the console is just telling me I have a function there, not the value of the answer. I have run into this before and feel if I can crack it I will be a much better human being.
So if anyone can explain in baby-language what I am misunderstanding I would be grateful.
Thanks
S
var where = function () { ... };
and
function where() { ... }
are essentially synonymous here. So, where is a function. You are calling that function here:
if (where()<=0)
However, the function does not return anything. You need to return the value from it, not just call sym.getSymbol("Man").getPosition() inside it.
That, or don't make it a function:
var where = sym.getSymbol("Man").getPosition();
if (where <= 0) ...
The value will only be checked and assigned once in this case, instead of updated every time you call where().
Try
var where = function()
{
return sym.getSymbol("Man").getPosition();
};
Your code wasn't returning anything.
var where = function() {
return sym.getSymbol("Man").getPosition()
}
console.log(where);
if(where()<=0) {
var playMan = sym.getSymbol("Man").play();
} else {
var playMan = sym.getSymbol("Man").playReverse();
}
String.prototype.parse = function(f) {
alert(this.replace(f, ""));
};
var a = "Hello World";
parse.apply(a, ["Hello"]);
Is the code correct?
No, that’s not correct. The function is defined as String.prototype.parse, so it is not available as parse (in fact, parse is undefined).
You could run it like the following:
String.prototype.parse.apply(a, ["Hello"]);
But actually, the reason why you add the function to the prototype of String is that you extend String objects with that function. So you actually should just run the function like this:
a.parse("Hello");
edit:
Oh, and in response to your question title “Why does this function return as undefined?”: The function doesn’t return anything, because you don’t tell the function to return anything. You could for example define it like this to return the replaced string (instead of alerting it):
String.prototype.parse = function(f) {
return this.replace(f, "");
};
And then you could alert the return value of the function:
alert(a.parse("Hello"));
There is no such variable parse defined in your code sample. If you really want to apply the function later on, you should do this:
// Capture function as a local variable first
var parse = function(f) { alert(this.replace(f, "")); };
String.prototype.parse = parse;