Problems with calling function inside function using `this` - javascript

window.onerror = function(e){alert(e)};
function main(){
this.work = [];
this.start_working = function() {
try{
if(this.work.length > 0){
var y = this.work.shift();
y.func(y.args);
}
}
catch(e){alert(e)};
};
this.add_work = function(f, a){
this.work.push({func:f, args:a});
};
this.foo = function(){
function footoo(){alert("bar");}
this.add_work(footoo);
};
this.foothree = function(){
this.add_work(this.foo);
};
this.start = function(){
setInterval(function(){this.start_working();}.bind(this), 1);
};
};
x = new main();
x.start();
x.foothree();
This is the watered down version of a function I am using elsewhere to run animations sequentially.
Expected behavior:
this.foothree is processed by the interval adding foo to the interval. this.foo is then processed adding footoo to the interval which is finally processed alerting "bar".
Problem:
when this.foothree is processed, an error is thrown:
TypeError: this.add_work is not a function.
Why don't I use something simpler:
Basically I need a function which allows me to compose a more complex animation made of simpler animations to the queue to be processed so I can reuse that animation. Foothree in this instance is just simulating a call which would add the real animation, footoo, to the queue to be processed. Footoo would be composed of simpler animations, foo, which would be executed sequentially.

this returns the [[ThisValue]] property of the EnvironmentRecord of the LexicalEnvironment of the ExecutionContext of the running function (see the spec).
Its value depends on how the function is called. If you call
this.foo = function(){
function footoo(){alert("bar");}
this.add_work(footoo);
};
in the function being declared there is no add_work method.
You should adopt var _self = this; pattern in order to point the correct calling context.
Basically the code should be rewritten as follows:
function main(){
var _self = this;
this.work = [];
this.start_working = function() {
try{
if(_self.work.length > 0){
var y = _self.work.shift();
y.func(y.args);
}
}
catch(e){alert(e)};
};
this.add_work = function(f, a){
_self.work.push({func:f, args:a});
};
this.foo = function(){
function footoo(){alert("bar");}
_self.add_work(footoo);
};
this.foothree = function(){
_self.add_work(_self.foo);
};
this.start = function(){
setInterval(function(){_self.start_working();}, 1);
};
};
Edit:
removed .bind(this) from original code.

This question has two components.
First it is a question about this in JavaScript aka the "target" or "receiver" of a function.
The target of a function in JavaScript depends on whether you are in strict mode, how the function was called and whether it was bound using bind.
Assuming strict mode (you should always put 'use strict'; at the top of your JavaScript):
foo(); // this inside foo will be undefined
a.foo(); // this inside foo will be a
a.foo.call(o); // this inside foo will be o
a.foo.apply(o); // this inside foo will be o
a.foo.bind(o)(); // this inside foo will be o
The second aspect to this question is what the author is attempting to do. I am pretty sure the complexity he is introducing to chain animations is unnecessary, and that he should be using requestAnimationFrame, but discussion of this would require another question.
Example:
function foo() {
document.write('foo', this, '<br/>');
bar();
}
function bar() {
document.write('bar', this, '<br/>');
}
foo();
document.write('------<br/>');
foo.call({});

Related

Call member function from constructor

I'm new to Javascript's Object Oriented programming (from C++ area).
I want to know the best practice of calling member function from constructor.
Following is a working piece of code:
Obviously the "initialize" is declared ahead of the invocation "this.initialize();"
function Foo() {
this.initialize = function() {
alert("initialize");
};
this.hello = function() {
alert("helloWorld");
this.initialize();
};
this.initialize();
};
var f = new Foo();
f.hello();
If I change the code as following, it will fail at "this.initialize();".
Question 1 Why is that? Won't the Javascript Engine firstly read in all member function declarations of an object?
function Foo() {
this.initialize(); //failed here
this.initialize = function() {
alert("initialize");
};
this.hello = function() {
alert("helloWorld");
this.initialize();
};
};
var f = new Foo();
f.hello();
Then I made the change like this.
The function "initialize" is executed on construction, however, the calling for "this.initialize()" in function "hello" failed.
function Foo() {
this.initialize = function() {
alert("initialize");
}();
this.hello = function() {
alert("helloWorld");
this.initialize(); //failed here
};
};
var f = new Foo();
f.hello();
Question 2: is the first piece of code the only way of calling member function from the constructor?
Update:
if I have to define a function before using it, Question 3: why following code works?
function Foo() {
this.hello = function() {
alert("helloWorld");
this.initialize();
};
this.initialize();
};
Foo.prototype.initialize = function() {
alert("initialize");
};
var f = new Foo();
f.hello();
Question 4:
Why following code succeeded? (considering the "future" function is defined after calling)
alert("The future says: " + future());
function future() {
return "We STILL have no flying cars.";
}
In the first case, you are calling initialize before it is defined (on the next line).
In the second case, you are assigning the return value of the function (undefined in this case) to this.initialize, so when you try to invoke it as a function later, you get your error.
You may want to look further into the prototype pattern for making class-like structures - Douglas Crockford wrote a lot of useful stuff on this and it's useful for introductory learning: http://javascript.crockford.com/prototypal.html is a good start.
My answers inline (kind of)
Question 1 Why is that? Won't the Javascript Engine firstly read in all member function declarations of an object?
No, if they are defined as in your example, they will be executed in order, as the method doesn't exist yet, it will throw.
This way would be a different case (not OO, but to ilustrate):
function Foo(){
initialize(); //This would work
function initialize(){ ... } //Parser defines its function first
}
In this case, the parser does define the function declarations first, it's a different case.
The function "initialize" is executed on construction, however, the calling for this.initialize() in function "hello" failed.
this.initialize = function() {
alert("initialize");
}(); //This executes the function!
The problem with the above code is that you're not assigning the function to this.initialize, you're assigning the result of its execution, in this case undefined (because there is no return inside the function)
for example, if the code were:
this.initialize = function() {
return 2;
}();
then this.initialize would be... 2 !! (not a function).
Hope this helps. Cheers
Calling a method from constructor :
var f = new Foo();
function Foo() {
this.initialize(); //failed here
};
Foo.prototype.initialize = function() {
alert("initialize");
};
Execution Process:
1) All functions are created (that are defined at the root)
2) Code is executed in order
3) When Foo is created/constructed it executes the code.
It try's to run Initialize() but it doesn't find it,
it throws an internal exception that is caught and
then creates the Prototype method and executes it.
4) If the Foo.Prototype.initialize line came BEFORE the,
"var f = new Foo()" then the initialize function would have existed.
This process occurs for every line of execution.

Does the var becomes a function because of a javascript function stored in a var?

In below example about Scope, I dont understand that how could a variable is running as a function? in here var f is running as f(). However, is this a sound method to run f in JavaScript? Why? Is it because var f stored a function?
var myFunction = function() {
var foo = "hello";
var myFn = function() {
console.log( foo );
};
foo = "ddd";
return myFn;
};
var f = myFunction();
f(); // "ddd"
Thanks!
This line of code will run the function myFunction and assign its return value to f.
var f = myFunction();
myFunction returns a reference to the function myFn. As a result, f is now a reference to myFn and when you attempt to call f using f() it calls myFn because that is where the reference points.
jsFiddle Demo
There is a similar approach which returns an object with functions
var init = function(){
return {
hello: function(){ console.log("hello"); },
world: function(){ console.log("world"); }
};
};
Which could then be used like this:
var f = init();
f.hello();
f.world();
In scripting languages in general and functional programming. You can use functions as you would a variable. For example: in both paradigms typically(not aware of any languages that don't) functions can be passed as parameters, etc...
Functions are objects in javascript, so they can be assigned to variables and passed around like any other value. And eventually they can be executed.
What's happening here is that myFunction returns a function, which can then of course be executed.
Let me simplify your example:
// function that returns a function.
var foo = function() {
// declare a function, but don't run it right now.
var fn = function() {
return "bar";
};
// return the function object.
return fn;
}
var someFn = foo(); // function object is returned from foo()
someFn(); // "bar" is returned
// Which means you could also do this!
// the first () executes foo, second () executes the function returned by foo()
foo()() // "bar" is returned
In this example, foo() returns a function. This function is saved to the local variable someFn and then executed.
Functions that return functions are a little tricky to wrap you head around sometimes, but it's one of the most powerful features of javascript as it allows you do some very tricky things.

Javascript - revealing object and variable scope

http://jsfiddle.net/ZLH7J/1/
What the jsFiddle and code below shows are two examples that essentially do the same thing. When trying to call first(); or this.first(); in either example, an undefined error is thrown. I can call the functions later through the instance, but not when trying to instantiate the object using init(){...}() like a constructor. I put init() at the bottom thinking it was an order of operations thing, but that is not the case. This does not work the way I thought it would work.
I am curious to understand how this is supposed to be done, and why this cannot be done.
//create and return an obj
var fishSticks = function(){
return {
first: function(){
document.getElementById('output').innerHTML="Success";
},
init: function(){
try{
first(); //err
this.first(); // also err
}catch(e){
document.getElementById('output').innerHTML=e.toString();
}
}()
}
}
//do function stuff and then return 'this'
var fishFillet = function(){
var first = function(){
document.getElementById('output2').innerHTML="Success";
}
var init = function(){
try{
first(); //err
this.first(); // also err
}catch(e){
document.getElementById('output2').innerHTML=e.toString();
}
}()
return this;
}
var test = new fishSticks();
var test2 = new fishFillet();
​
You need to understand two things:
1) JavaScript does not automatically insert this like Java does, so the first() call will only look through the lexical scope for a definition of first, it will nok look at the this object. Therefore the call to first() should work but this will be bound to something else than what you might expect inside first.
2) Local variables in a constructor do not become members of the constructed object.
In your second example, if you comment out the call in "init" to this.first() then you get the "Success" message.
The first version doesn't work because JavaScript simply does not allow for references to be made within an under-construction object to the object itself. There's just no way to do it.
The second one works (well the simple reference to "first" works) because "first" is declared as a local variable. Local variables are not properties of any object, and in particular they're not properties of the object allocated when the function is called with new. That's why this.first() doesn't work.
In the second one, you could make this.first() work by declaring things differently:
var fishFillet = function(){
this.first = function(){
document.getElementById('output2').innerHTML="Success";
}
var init = function(){
try{
this.first(); //will work
}catch(e){
document.getElementById('output2').innerHTML=e.toString();
}
}()
return this;
}
Also, for what it's worth, the weird anti-pattern of
var something = function() { ... }
is not as useful as
function something() { ... }
There's no reason to use the var declaration instead of the function declaration.
How about...
var fishFillet = function () {
var first = function () {
document.write( 'Success' );
};
var init = function () {
first();
};
init();
return {
first: first
};
};
And then:
var ff = fishFillet(); // calls init() which calls first()
ff.first(); // call first() manually
Live demo: http://jsfiddle.net/uaCnv/
So, first you define all your functions, next you manually invoke init, and last you return an object containing those functions which should be available through the resulting object (as methods).
Since you are using both as a constructor, format them as such:
function fishFillet(){
this.first = function(){
document.getElementById('output2').innerHTML="Success";
}
this.init = function(){
try{
this.first();
}catch(e){
document.getElementById('output2').innerHTML=e.toString();
}
}
}
var food = new fishFillet();
food.init();
The reason it wasn't working for you is b/c "first" is created as a local varaible, and is deleted after execultion. Init isn't being called until after the execution of the constructor has finished

How does 'call' work in javascript?

I have a question on 'call' in javascript.
var humanWithHand = function(){
this.raiseHand = function(){
alert("raise hand");
}
}
var humanWithFoot = function(){
this.raiseFoot = function(){
alert("raise foot");
}
}
var human = function(){
humanWithHand.call( this );
humanWithFoot.call( this );
}
var test = new human();
so..when I use 'call' as humanWithHand.call(this), what happens internally?
does humanWithHand variable copies (or points?) its properties and members to human variable's prototype?
Yehuda Katz has a good writeup of JavaScript's Function#call method. His writeup should answer your question, and many followup questions besides.
When you call a function directly, using the general syntax:
var foo = function() {
console.log("foo");
return this;
};
foo(); // evaluates to `window`
Then this inside the function call is whatever this is outside the function call. By default, in the browser, this outside any function calls is window. So inside the function call as above, this is also by default window.
When you call a function using the method-call syntax:
var bar = {
foo: function() {
console.log("foo");
return this;
}
};
bar.foo(); // evaluates to `bar`
Then this inside the function call is the object to the left of the rightmost period: in this case, bar.
We can simulate this situation using call.
When you set up a function outside an object and want to call it with this inside the function call set to an object, you can:
var foo = function() {
console.log("foo");
return this;
}
var bar = { };
foo.call(bar); // evaluates to `bar`
You can use this technique to pass arguments as well:
var foo = function(arg1, arg2) {
console.log("foo");
return arg1 + arg2;
}
var bar = { };
foo.call(bar, "abc", "xyz"); // evaluates to `"abcxyz"`
.call() sets the this value and then calls the function with the arguments you passed to .call(). You use .call() instead of just calling the function directly when you want to set the this value inside the called function rather than let it be set to whatever javascript would normally set it to.
.apply() is a sister function. It can also set the this value and it can take arguments in an array so it can be used when you are trying to pass a variable argument list from some other function call or when you're constructing an argument list programmatically which may have different numbers of arguments depending upon the situation.

Define an anonymous function as part of an object definition?

Suppose I have:
var myfunc = function() {
// do stuff
}
myfunc.foo = function() {
//do other stuff
};
Now myfunc has a property foo that is a function, great. Is there a way to create myfunc from the get-go in this state? That is, I want foo to be defined when myfunc is created. The syntax, I would imagine, is something like:
var myfunc = {
:function() {
// do stuff
},
foo: function() {
// do other stuff
}
}
Except that's wrong.
You can place an anonymous function inside an object, however the only plausible way of doing this is to call the anonymous function when the object is initialised, otherwise the function will never be able to be called - it's anonymous!
Here's a JSFiddle: http://jsfiddle.net/g105b/99K5F/
var myfunc = function() {
this.foo = function() {
console.log("myfunc.foo called!");
};
(function() {
console.log("Anonymous function called.");
})();
};
// Initialising "myfunc" will call the anonymous function.
var instance = new myfunc();
// Now the foo method can be called.
instance.foo();
A little confused as to what functionality you are looking to gain here...
If you want some code to execute when the myfunc is defined, you could use the module pattern:
var myfunc = (function() {
var self = {};
// any initialization code can go here
alert("myfunc init code");
self.somePublicMethod = function () {
}
return self;
}());
This can also be called an immediate function, a function that is defined and executed at the same time.
From within the closure, and code that is not defined as part of another function will be executed when the object is defined, so when you do something like this:
myfunc.somePublicMethod()
the alert would have already been fired.
(This answer written before the first half of the question was significantly revised)
Now myfunc has a property foo that is a function
No, it doesn't.
You called it with myfunc() so this is a reference to the global window object, thus you are creating window.foo.
Possibly what you are looking for is:
function myfunc () {
// do stuff when myfunc is called
}
myfunc.foo = function () {
// do stuff when myfunc.foo is called
};
or perhaps:
function myfunc () {
// do stuff when myfunc is instantiated
this.foo = function () {
// Add a foo property to this when myfunc is instantiated
// ... which is only worth while if you are doing pretty
// ... odd stuff with the variables that are passed in
}
}
var instance = new myfunc();
or maybe:
function myfunc () {
// do stuff when myfunc is instantiated
}
myfunc.prototype.foo = function () {
// Have a foo function on every instance of myfunc
}
var instance = new myfunc();
… but you've abstracted the problem you are trying to solve away in your question, so it is hard to tell what you are actually trying to achieve.
You can use jQuery:
var myFunc = jQuery.extend(
function() { ... },
{
bar: "wioll haven be",
foo: function() { alert(myFunc.bar); }
}
);
myFunc();
myFunc.foo();
This is mostly code acrobatics, this is probably the closest you'll get:
var myfunc;
(myfunc = function(){}).foo = function(){};
There is no practical difference in declaring methods later though, since javascript is single-threaded.

Categories