how do you pass an instance function to an outside function? - javascript

let's say I have I have the following in a file called file1.js:
//constructor
function Blah(){
this.string = "hello there agent ";
}
//'method'
Blah.prototype.greeting = function(num){
return this.string + num;
}
Then in a file called file2.js I then have this:
function combine(num,funct){
return funct(num);
}
And then finally, in an html file called file3, I have this:
var bond = new Blah();
document.write(combine(007,bond.greeting));
I am actually getting into the "greeting" method, but for some reason, the return value, instead of being a string, winds up not being NaN. Any idea why? the greeting() method seems to be ran at the proper time. However, despite that, 007 seems to be getting interpreted as NaN anyway. Again, any suggestions as to what could be causing this?
Thanks a bunch in advance

First, depending on how you call the greeting method, the this value will be different. If you call it like bond.greeting(num) then this will be bond. If you call it like funct(num), where funct is bond.greeting, then this will be the global object. You need to bind this permanently when passing the function along, to maintain its value no matter how you call the function.
Second, 007 === 7. If you want to print out 007 literally, then you should use a string:
combine('007', bond.greeting.bind(bond));
Remember, this depends on how the function gets called, it is dynamic, and resolved an runtime, unless you bind it previously, like we did above.

You're experiencing the special characteristics of the this keyword.
Basically, this resolves to whatever you call a function from. In your case, you're calling it from the global scope from through func(), which makes this == window. (Calling it through bond.greeting() makes this == bond.)
To resolve, this either bind the function or force the resolution:
// note that this method requires a shim for IE 8 and older
document.write(combine(007,bond.greeting.bind(bond)));
or
function combine(num, obj, funct){
// since funct is being called from obj, `this` == obj within the function
return obj[funct](num);
}
document.write(combine(007,bond, 'greeting'));

The problem you have is when you pass the function as argument, it is passed by value, and then you loose the reference to the object who has the element string = "hello there agent "; and when the function is executed, it executes "this.string" which doesn't exist inside the function, it returns undefined. It's a scope issue.
The solution to make it work good, is to pass the reference which is the object bond
function combine(num,obj){
return obj.greeting(num);
}
combine("007",bond); // returns "hello there agent 007"

1) NaN is "Not a number" error. Try encapsulating 007 in quotes
2) Do you need file2.js or could you do without it?
var bond = new Blah();
document.write(bond.greeting("007"));

Related

When and when not to use 'return' keyword in a funciton?

I have learned in "Function section" of the Javascript course in Codecademy that: to call a function, we have to use 'return' keyword inside the function. But in the "Array section" of the Javascript course found a function can be called without using 'return' keyword inside that function. Can anyone explain when I must use 'return' keyword inside the function and when it is optional?
I am attaching the code snippet for Your reference.
const flowers = ['peony', 'daffodil', 'marigold'];
function addFlower(arr) {
arr.push('lily');
}
addFlower(flowers);
It is not necessary that function must return any value.
When you not required anything from the function then you don't require to return anything. This function called void function.
If you require some value from function the you must return it.
The return keyword is used only to get back some value from the function to the caller so that the value can be used later. In case, if you don't want to use any value from the function, you can omit the return statement.
In the case of objects as a parameter, if that object itself is changed, then it will change the original copy which was passed as well. So, at that time also, no need to return that object from the function.
With the return statement you actually return a value to the caller. For example:
function add(a, b) {
return a+b;
}
var c = add(5,7);
If you have a function that just performs a task without a return value you do not use the keyword. E.g.:
function sayHello() {
console.log('Hello');
}
sayHello();
Note: A return statement ends the function; statements after the return will not be executed.
In fact, there might be a need for returning a value, just like Array.prototype.push() is doing it. Please see the documentation of MDN Web Docs.
function addOneFlower(flowers) {
const newFlower = "Bellflowers";
return flowers.push(newFlower);
}
const flowerArr = [];
let sizeOfFlowerArr = addOneFlower(flowerArr);
// sizeOfFlowerArr starts with 1
sizeOfFlowerArr = addOneFlower(flowerArr);
// sizeOfFlowerArr increased to 2
Use return when you might want to transfer information from inside the function directly to the caller. For example, maybe a caller of addFlower would want to know the name of the flower that was added. Then you would probably have something like
const addedFlower = addFlower(flowers);
This assigns the return value of addFlower to the addedFlower variable. But for that to work, addFlower should return something, eg:
function addFlower(arr) {
arr.push('lily');
return 'lily';
}
If you don't ever need to transfer information directly from inside the function to the caller, then all invocations of the function should be in a standalone line, like
addFlower(flowers);
and there's no need (or sense) for addFlower to return anything.
Note that the caller may sometimes want information that the function returns, but sometimes a caller may not care about it. But the function may not know which, so it should return regardless, and the caller of the function can use the resulting expression if it wants, or the caller can ignore it. Eg, in the same script, there might be one line like
const addedFlower = addFlower(flowers);
and another like
addFlower(flowers); // Don't care about the return value
In this case, addFlower should be returning something regardless, leaving it completely up the caller to do something with the result.
The function when called will run till it reaches a return statement, or the end. If you are using a function with return value, you need to have a return statement in your function definition.
But if you are using a function with no return statement and it can run till the end of the function, than you don't have to have a return statement in the function definition. For example:
function helloWorld() {
console.log('Hello World');
}
the simple example I can give you is this.
let say you have some unknown numbers you want to calculate when the user gives you an input.
for example, you ask your users when he/she was born to calculate his/her age.
function calcAge(yearBorn){
var age = 2019 - yearBorn;
return 'hello user your age is ' + age;
}
calcAge(1993);
when the user gives you the year she/he was born, it will be passed to the yearBorn parameter and will be calculated against the current year. but to use it, you should return it. if you don't return it you will get 'undefined', when you call the function. You have probably seen the console.log() function previously. it is used only on the dev tool in the browser for development purposes. if you want to use the end result from that function, you should use the return keyword then you will get the calculated age instead of 'undefined'! this has something to do with function scope. if you declare the age variable outside of the function and reassign it again in the function, you can probably use the age without the return statement like below.
var age2;
function calcAge2(yearBorn){
age2 = 2019 - yearBorn;
}
When you call it, since the age2 is declared outside of the function, you will be able to access it from the global scope. even if you didn't return it, the function call will update the age2 variable based on the calculation. but declaring a variable in the global scope is not a good practice.
in your example, you have already declared the variable outside of your function.
with const flowers = ['peony', 'daffodil', 'marigold'], you are only pushing additional items in your array by calling the function. if you had declared your flowers array inside the function like bellow, though it is not the best example
function addFlower() {
const flowers = ['peony', 'daffodil', 'marigold'];
flowers.push('lily');
return flowers;
}
then you have to use the return statement to return the value of the array to use it later.
in your case, you are just adding the items in your pre-existing array that was declared in the outer scope.
you don't have to use return if your intention is not to return the value from the function local scope.
since you declared your variable outside of the function, you can update those values without a return statement like you did. but if you want to return a value from a function to be used, you should use the return statement.
check the two examples below. copy them and play around with them in the console.
On the first one since I declared the variable sum inside the function (in the local scop), I have to use the return statement to get the value that is calculated when I call the function. otherwise, the function call will give me undefined value;
function add(x, y){
let sum = x + y;
return sum;
}
but on the second one, the sum variable is declared outside of the function in the global scope. all I am doing when I call the function is updating the pre-existing variable sum. because of that, I don't need to use the return statement here
let sum;
function add(x, y){
sum = x + y;
}
My advice to you, the more you learn about javascript, the dot will connect for you. just keep learning. I have been there. sometimes it feels like nothing makes sense. trust me the dots will connect as you learn more.

Passing "extra" arguments to a function stored in a variable - Javascript

I'm new to Javascript, I'm self-teaching, so this might be an obvious area, but no matter how I phrase the question I can't really seem to get my head around this one issue. At the moment I'm reading through http://eloquentjavascript.net/chapter6.html (which was on mozilla's MDN). I've come across this a couple of times now, I would just like a simple break down if possible.
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
show(isNotNaN(NaN));
I don't understand how at the very last step isNotNaN (a variable) is passing an 'extra argument' (NaN) to the function stored in isNotNaN (negate(isNaN). "show(isNotNaN(NaN));"
I came across this same problem when the concept of enclosure was trying to be explained. But I don't get where this argument "NaN" is going in the above function, as it seems to me like the last statement ends up something like:
show(negate(isNaN, NaN));
I would be happy to provide more details. This concept of passing an extra argument to a variable already holding a function with an argument confuses the hell out of me!
There's no "extra" argument. The negate() function itself returns a function defined as a function expression, which can then be called with any number of original (not extra) arguments passed. A closure is used for the returned function to keep a reference to isNaN as func.
var isNotNaN = negate(isNaN);
At this point, isNotNaN contains a reference to the function
function(x) {
return !func(x);
};
Again, func here refers to the isNaN argument passed to the negate function, which is the immediate parent in the scope chain. The result is similar, but not the same as
var isNotNaN = function (x) {
return !isNaN(x);
};
The reason it is not the same is, if we change the value of isNaN, the behaviour of this function will change. In the example you posted, however, the value of func is equal to the original value of isNaN and cannot be changed by anything outside of its scope thanks to the closure.
Essentially, you can pass in any function and get a new function that returns the negated result of the original function in return. For example:
var isNotArray = negate(Array.isArray);
isNotArray(12);
//-> true
In fact, negate(isNaN) simply return a function to the variable isNotNaN. This function take a parameter (named x in your case), then execute the function isNaN on the parameter before negating it and returning the result.
Perhaps this example can clear some things out for you regarding closures:
function foo(x){
function bar(y){
return x+y;
}
return bar;
}
var fooRef = foo(1); // fooRef references foo() with x set to 1
console.log(fooRef(2), foo(1)(2)); // 3, 3
http://jsfiddle.net/ePwy8/

Execute private function inside the class by its name (string)

At the moment I have simple JavaScript class like this:
function MyClass() {
// ... some code ...
this.Create = function() {
funcName = 'myTestFunc()';
cTimer = setTimeout(funcName, 1000);
}
// ... more code ...
var myTestFunc = function() {
alert ('everything\'s OK!');
}
// ... more code ...
}
and to test it I'm using this code:
x = new MyClass();
x.Create();
I have some troubles to execute this function by it's name. If I put just eval(funcName); instead of setTimeout call it works fine but can't figure out why it doesn't work this way.
Course, this is part of more complex code but rest of code is irrelevant to this problem.
My question is obvious - How to execute function by its name set as setTimeout function's argument? Is it possible?
Note: Making this function public (this.myTestFunc = ...) isn't an option!
Update:
funcName = "myTestFunc()"; is just an example. In real code it looks like funcName = getRandomEffectFunctionName();! It's just a random value.
Referring to the update:
Instead of setting:
var funcName = "getRandomEffectFunctionNeme()";
Thus, setting a reference to the function's name you should do
var funcRef = getRandomEffectFunctionNeme;
And set a reference to the function itself . Not only this avoids the issues setTimeout with strings has*. It also solves your closure issue since your code is structured in such a way the timeout has access to the function itself.
In your case, let's assume you have some functions that are filters, for example lowPass highPass and blur. In that case, instead of choosing a function name we would be choosing a function.
First, we store these functions in an array:
var filters = [lowPass,highPass,blur];
In JavaScript, functions are first-class objects, you can pass them around just like other objects.
Next, we'll get a random number
var chosen = Math.floor(Math.random()*3);//get a random number between 0 and 2
Finally, we'll choose the filter and invoke it
var filter = filters[chosen];
setTimeout(filter,1000);
( * just try debugging it, it basically invokes the compiler whenever ran and is painfully slow)
You just pass a function to setTimeout as a parameter, rather then a string, setTimeout(myTestFunc,1000) .
When calling Create it would have access to it anyway because they are in the same closure.
NOTE: This solution is only applicable if you can not pass the function name as a function reference, for example if you're integrating with code that is outside your control. Generally, when possible, you should pass a function reference since in JavaScript, all functions are objects.
Assuming that the timeout and the function are in the same closure your code is pretty close. The problem is that your eval call executes in the global context because it is in a timer. This means they are no longer in the same lexical scope.
You can however, grab a reference to the function by clever use of eval which you can later call in the setTimeout invocation.
var F=eval(funcName);// gain a reference to the function given the function's name
cTimer = setTimeout(F, 1000);
If you're using AIR or don't trust the functionName string you can do the following:
function Test(){
var functionContainer={
t:function(){
console.log("it's t");
}
};
this.callT=function(functionName){
var F=functionContainer[functionName];
console.log("F is:",F);
setTimeout(F,500);
}
}
(new Test()).call("t");
This is preferable since you are invoking setTimeout with a function's name and not a string. In general, using setTimeout with a string can have issues, it's hard to debug or maintain.

Javascript function syntax needs explanation

return this.foo("abc",function(){
//do something
});
Can some one tell me what does the above line do?
THanks
It grabs a reference to this, which might be the DOM Window, a DOM element, or any other JavaScript object depending on how and where the above code is being run.
It (skipping ahead) prepares a new anonymous Function that //does something.
It attempts to invoke a method foo on object this, passing in two parameters "abc" and said anonymous Function.
Very often when you see code that passes along an anonymous function (e.g. function(){ ... }), it is in fact holding on to that function in order to execute it not right away but at some later point in time, such as in response to a click event or a timer.
It calls the function referenced by this.foo and passes two parameters: The string "abc" and an anonymous function function(){ //do something}. It then returns the result.
It is equivalent to:
var a = "abc";
var b = function(){
//do something
};
return this.foo(a, b);
Functions are first class objects in JS so you can pass them around like any other value.
I recommend to have a look at the MDC JavaScript guide.
looks like this.foo() is a function that returns something. so the return value is, what this.foo() returns.
calls an instance method that gets as parameters a string and a function.
It will return (yeah, like it is in English) the returned result of a function this.foo(...) (in the most simple form, ithe function this.foo(...) return "something" then the code will return "something"). The function this.foo("abc", function(){...}); is itself a function which receives 2 arguments: A string "abc" and a function(). The function this.foo will do something and return "something" to return by the main function.
[x]

Using a new operator - from John Resig #36

This example code below is #36 in John Resig`s Learning Advnaced JavaScript. http://ejohn.org/apps/learn/#36
It is called We need to make sure the
new operator is always used.
Six Questions - I would appreciate as much detail as you can provide
1) Is function User ever actually called in this code? I note that when it says assert(user...), user is lower case. If the function gets called, how? does it get called when it asserts the variable user, which has a function call attached to it i.e. User("John," name)
2) If Im correct in assuming that function User is never called, is there a way that the codethis.name = first + " " + last;` is run?
3) If the function User is called, or if it were to be called, can you please explain the order of operations inside the function User. For example, it returns new User before it does this.name = first + " " + last; how would that work if this function were called or is called?
4) in what way could !(this instanceof User) if be true. since the function User is the object, wouldn`t "this" always be an instance of itself?
5) regarding the first assert i.e. assert(user, "this was defined correctly, even if it was by mistake"), can you please explain how it was defined correctly, and, importantly, please explain how it was a mistake? How should it have been done so it`s not a mistake?
6) regarding the second assert, why is it a noteworthy that the right name was maintained? Isnt it as simple as variablenamehaving been assignedResig`. In what way might you have expected name to change?
function User(first, last){
if ( !(this instanceof User) )
return new User(first, last);
this.name = first + " " + last;
}
var name = "Resig";
var user = User("John", name);
assert( user, "This was defined correctly, even if it was by mistake." );
assert( name == "Resig", "The right name was maintained." );
This example is demonstrating a fundamental flaw in JavaScript's design, which is that calling functions intended to be used as constructors without the new operator can cause unintentional modification of the global object.
User is called on this line: var user = User("John", name);. Lowercase user holds a reference to the new uppercase User instance.
See #1.
If User is called without new, then this will not be an instanceof User. When this happens, we immediately call new User(...). In this second call, this will be an instanceof User, so the conditional block is skipped and we simply continue on with the constructor, creating a new instance of User as originally intended.
When it's called without the new operator, the value of this in a function simply refers to the global object, which is window in a browser. This is a serious mistake in the design of JavaScript, for which this exercise is demonstrating a workaround.
Because there is no explict return from the User constructor (without the instanceof check's block) , if User were called without new it would return undefined and the assert would fail. The instanceof check prevents this.
Without the protection of the instanceof check, calling User without new would cause unexpected results. Since this would refer to window, the assignment to this.name would update window.name, not the name property of a new User instance, and the assert would fail.
Any given function object can be used two ways.
As a function
As a constructor
The difference being the value of the this binding. When you use a function as a constructor the this binding will be a new object that inherits from the constructor's public prototype. Normally calling a function will set the this binding to the global object. (With strict mode in ES5 this will not happen.)
The second assert is very important now that you know that the this binding can be coerced to the global object.
A Simplification of Calling a Constructor
function ConstructUser(fname, lname) {
var obj = {}; // Empty Object
// In reality a special internal Prototype property
// is assigned rather than 'obj.prototype'.
if (User.prototype instanceof Object) {
obj.prototype = User.prototype;
} else {
obj.prototype = Object.prototype;
}
// Now call the User function with the
// new object as the 'this' binding.
User.call(obj, fname, lname);
return obj;
}
1) Is function User ever actually called in this code? I note that when it says assert(user...), user is lower case. If the function gets called, how? does it get called when it asserts the variable user, which has a function call attached to it User("John," name)
Yes. It is first called with this bound to the global object (see caveat below), and then it calls itself with a blank object whose prototype is User.prototype bound to this.
The first "call" invokes the builtin function call operator, and the second "call" invokes the builtin function construct operator. For user defined functions the two are the same, but the spec does distinguish between the two.
2) If I'm correct in assuming that function User is never called, is there a way that the code this.name = first + " " + last; is run?
Yes. The second invocation will reach that since in the second invocation this is a User.
3) If the function User is called, or if it were to be called, can you please explain the order of operations inside the function User. For example, it returns new User before it does this.name = first + " " + last; how would that work if this function were called or is called?
A call does not return until the body finishes. So the "call" invocation starts, which starts the "construct" invocation, which returns, yielding the new User which is then returned by the first invocation.
4) in what way could !(this instanceof User) if be true. since the function User is the object, wouldn`t "this" always be an instance of itself?
No. If the if statement were not there, User.call({}, "John", "Doe") would cause User to be "called" with this bound to a blank object. Try running
var notAUser = {};
User.call(notAUser, "John", "Doe")
alert(JSON.stringify(notAUser));
and you should get
{ "name": "John Doe" }
5) regarding the first assert i.e. assert(user, "this was defined correctly, even if it was by mistake"), can you please explain how it was defined correctly, and, importantly, please explain how it was a mistake? How should it have been done so it`s not a mistake?
It is the author's opinion that not putting new before User was a programmer error.
6) regarding the second assert, why is it a noteworthy that the right name was maintained? Isnt it as simple as variablenamehaving been assignedResig`. In what way might you have expected name to change?
The global variable name is a property of the global object. If this is bound to the global object, then assigning this.name would change the global variable.
Caveat:
For language-lawyers,
According to the language spec when you call a function as a function, not as a method, this is bound to null. Another part of the spec says that when you read this, if it is null, what you get back is the global object instead. This difference is significant in the case of EcmaScript 5 strict mode, because that changes the second part so that no funny stuff is done when reading this. If this is null, reading it will give you back the value null.
EDIT:
The construct operator is only defined in the JavaScript spec. The new operator in the JavaScript language is the way you invoke it.
For user defined functions, it works as follows:
Code calls new f(arg1, arg2)
JS interpreter allocates space for a new object and sets its prototype to f.prototype.
JS interpreter invokes f with this set to the new object and with arg1 and arg2 as the actual parameters.
If f returns an object, that is used as the result of new instead.
Otherwise, the new object is used. If you return any non-object value, even a string or number, then the new object is the result of new.
1.the function User is called at var user = User("John", name);
2.pass
3.I didn't understand your question.
4.
user = User("a", "b");
would do that.
5.user = new User("a", "b"); is the correct one.
6.I don't know.

Categories

Resources