My programing background is that I learned a little Java in school. JavaScript syntax tends to confuse me for some reason. The JavaScript code below is a pattern of syntax that I don't know what to make of:
foo.ready = function(variable){... var whatever = variable.bar();
One of my main points of confusion is the parameter. For a contrasting example, in Java, if I call a method with one parameter, the call sends one parameter. I don't see how the parameter named 'variable' is ever set.
The variable is assigned when foo.ready is invoked, and passed some value (presumably a function).
var foo = {}; // 1. Create an object named "foo"
// 2. Assign a function to the "ready" property of "foo"
foo.ready = function(variable) {
// 4. "foo.ready" has been invoked, and received a function to its
// "variable" parameter, which it then invokes.
// The return value is assigned to "whatever"
var whatever = variable();
alert( whatever ); // 5. alert the value returned from the function
};
// 3. Invoke "foo.ready" passing a function as the argument.
// The function merely returns a string
foo.ready( function() { return "Hello world"; } );
Here's a working example: http://jsfiddle.net/69grz/
variable can be much more than a real variable, it can also be a function or a handler/object. In this case you call the function bar() on the object variable
foo.ready refers to an entire function. You can call foo.ready(), with any number of arguments, too. This is a typical call-back pattern: Whoever is in charge of the foo object wants to call you back when she's ready, so you pass this function to her.
You can't really control how many variables (of any type!) will be passed to your function, but presumably the documentation will have told you that you'll receive at least one.
Here is some code that makes that work:
// foo is an object
var foo = {};
// Create a function and assign to the ready property
foo.ready = function(variable){
var whatever = variable.bar();
};
// Create an object that contains a function named bar
var x = {
bar: function(){ return 42; }
};
// Call the function in foo with the object as parameter
foo.ready(x);
The expression variable.bar() will call the function in the object x which returns the value 42, which is then assigned to the variable whatever.
Related
I found that there are these two ways that a variable property value can be updated on a function call
Example 1:
function bar( arg ) {
return arg + 1;
}
var foo = {
num: 1
};
foo.num = bar( foo.num );
console.log( foo.num );
Example 2:
function bar( arg ) {
arg.num = arg.num + 1;
}
var foo = {
num: 1
};
bar( foo );
console.log( foo.num );
I want to know what are the proper naming convention for each of the method calls.
Also can anyone explain, how it is possible to update the original variable value inside a closed function operation as shown in example 2?
Primitive parameters (such as a number) are passed to functions by
value; the value is passed to the function, but if the function
changes the value of the parameter, this change is not reflected
globally or in the calling function.
If you pass an object (i.e. a non-primitive value, such as Array or a
user-defined object) as a parameter and the function changes the
object's properties, that change is visible outside the function.
Source : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
Well in javascript objects are passed by reference so when you pass a object to a function you're passing it's memory reference not a copy.
So when you update value in the function it updates the value at reference.
function bar(arg) {
arg.num = arg.num + 1;
}
var foo = {
num: 1
};
bar(foo);
console.log(foo.num);
When you pass a primitive value it is passed by value. It passes a copy of value so whatever changes you do in close function will not affect the original value.
function bar(arg) {
arg = arg + 1;
}
var foo = 1
bar(foo);
console.log(foo);
I want to know what are the proper naming convention for each of the methods.
There are no naming conventions for functions (I would only call them methods if they are directly associated to an object), except thar the name is camelCase. However there is a convention in functional programming that functions that return something are pure (they do not change anything, but just return something new, like your first function), and functions that return nothing are impure, they change something. Wether you strictly follow that pattern depends on your codingstyle, I follow that often but not always. It is also a bit harder in JS as JS is not typed.
also can anyone explain, how it is possible to update the original variable value inside a closed function operation as shown in example 2?
It is impossible. If you pass a number, it is passed as a value, you have no way to find out where that number belongs to. Thats a good thing as you can always keep track which function is able to mutate an object. bar(foo) is, bar(foo.num) is not.
Maybe the title sounds a little bit weird (please improve it) -- but I need a solution for the following scenario. I have the following code:
var Foo = function () {
this._hello = "world!";
};
Foo.prototype.bar = function () {
console.log(this._hello);
};
var f = new Foo();
f.bar(); // => "world!"
f.bar.apply(this); // => undefined
I know that apply changes the context, so inside of bar, this will be the global object (at the second call).
But what I need is to access this from Foo function. A solution that I see would be:
var Foo = function () {
var self = this;
self._hello = "world!";
self.bar = function () {
console.log(self._hello);
};
};
However, I would choose not to have method declarations inside of another function.
I'd prefer to define methods same column level (just for code style):
var Foo = ...;
Foo.prototype.method = ...;
Is this possible? How?
You can use the bind() method to tackle these kinds of problems. Instead of something.method(f.bar) call something.method(f.bar.bind(f)) to get the bar method always called on the expected context (f).
If you don't want to use bind in every location where you pass bar around as a callback, you can also put it in the constructor to create a dedicated bound function for every instance by default:
function Foo() {
this._hello = "world!";
this.bar = this.bar.bind(this);
}
Foo.prototype.bar = function () {
console.log(this._hello);
};
var f = new Foo;
something.method(f.bar); // works!
It's not possible to do this by assigning a function to the prototype like this.
Unless you assign something to f.bar directly (as in your second example, and Bergi's answer), the value you will get for f.bar is a reference to the function you assigned to the prototype's property Foo.prototype.bar. This will be exactly the same function object for any other object that has Foo.prototype as a prototype. There is no reference to f in this function object.
So when you call f.bar(), how does this refer to the value of f? It is a special syntax, that basically equates to f.bar.apply(f). It is only the fact that you use this method-call syntax that sets this to the value of f. Any other reference to f.bar will just evaluate to the prototype's single, shared function object.
If you call it with f.bar.apply(somethingElse), this is now set to somethingElse, and all association with f is lost.
It's not a question of apply(...) changing scope. fn.apply(x) sets this to x within fn, whereas y.fn() sets this to y.
Similarly, in your example if you assign f.bar to a variable and then invoke it via the variable instead of using the method-call syntax f.bar(), your this will be the window object (if running in a browser) and again you'll get undefined.
var func=f.bar; // now func === Foo.prototype.bar
func(); // => undefined
See also How to find the object a function belongs to?
I found this browsing:
What is the difference between a function call and function reference?
After reading the answers there, I did't understand the definition and usage for function references and function calls. Then I searched a lot, but it is still unclear where to use what.
Could you help me understand this by pointing out the differences in concept and usage? I want to make this as a reference for future programers.
Take this for example:
function foo() {
alert('foo');
return 'bar';
}
First of all, what is a function? It's a routine that can be called (or "invoked", or "executed"), and when you do so it usually does something, and returns some value.
So you have a function named foo. You can call it by adding () after its name:
foo();
You can store the return value in a variable, if you assign the result of the invocation to it:
var something = foo();
something === 'bar'; // true
But that's not all you can do with functions in JavaScript. It's a language where functions are first class citizens, so they can be passed around to other functions, and returned from other functions. They can also be stored as variables. For example:
var refToFoo = foo;
Now refToFoo is the same as foo. It's not a copy, it's a reference pointing to the same (internal) function object as foo. So you can use refToFoo just like you would use foo:
var something = refToFoo();
something === 'bar'; // true
refToFoo === foo; // true; they're the same object
Perhaps the most common use to function references is to use them as event listeners:
someElement.onclick = foo;
Note there is no parentheses above. It we used parentheses, foo would be invoked, immediately, and its return value would be assigned to the element's onclick method. Since that function returns a string, nothing would happen if the element were clicked. That's a very common mistake newbies do. Another common one is invoking a function instead of passing a reference to setTimeout:
setTimeout(foo(), 1000); // WRONG - foo is executed immediately
Compare that to:
setTimeout(foo, 1000); // RIGHT - we're passing a reference to the function,
// that will be invoked by the js engine after 1000ms
I hope this helps clarify your doubt.
I'm just trying to get a better understanding/confirmation of function arguments
In the function seen here:
function newFunction(data, status){
would the function apply specifically to data and status variables?
I don't quite understand how the arguments work.
Basic Scenario
When a function is defined, the () area is used for inputs. These inputs are mapped to what data is sent in.
function newFunction(data, status){
}
newFunction(1,2);
In this scenario, data will be assigned the value of 1, and status will be assigned the value of 2 for the scope of newFunction.
Missmatched inputs
However, it does not always directly map. If fewer arguments are sent, then the unassigned input variables become undefined.
function newFunction(data, status){
}
newFunction(1);
In this scenario, data will be assigned the value of 1, and status will be assigned the value of undefined for the scope of newFunction.
arguments object
Inside of the scope of newFunction, there is also access to the array like object called arguments.
function newFunction(data, status)
{
var args = arguments;
}
newFunction(1);
In this scenario, the variable args will hold the arguments object. There you can check args.length to see that only 1 argument was sent. args[0] will give you that argument value, being 1 in this case.
Function object
A function can be made into an object with the new keyword. By using the new keyword on a function, a Function object is made. Once the Function object is made, this may be used to refer to the current Function object instead of the global window.
function newFunction(data,status){
if( this instanceof newFunction ){
//use as a Function object
this.data = data;
}else{
//use as a normal function
}
}
var myNewFunction = new newFunction(1);
In this scenario, myNewFunction now holds a reference to a Function object, and can be accessed as an object through dot notation or indexing. myNewFunction["data"] and myNewFunction.data now both hold the value of 1.
This means that the function accepts both data and status parameters. The programmer calling the funciton (you) is required for providing the parameters when calling the function (also known as arguments.)
Let's look at a simplified example:
function add(x, y) {
return x + y;
}
The function here takes two numbers, adds them together, and returns the result. Now, as a programmer, you have the benefit of adding two numbers whenever you want without having to duplicate the functionality or copy/paste whenever you need your application to perform the same functionality.
Best of all, another programmer you work with can add two numbers together without worrying about how to do it, they can just call your function.
EDIT: Calling the function works as follows
var num1 = 10;
var num2 = 15;
var z = add(num1, num2); //z = 25
function newFunction(data, status){ ... function code ... }
This is the Javascript definition of a function called newFunction.
You can pass arguments to a function. These are variables, either numbers or strings, with which the function is supposed to do something.
Of course the function behaviour/output depends on the arguments you give it.
http://www.quirksmode.org/js/function.html
I have an object and it has another inner object. How can I call the parent object from the inner object?
var test = {
init: function () {
var instance = this;
},
call: function() {
this.stop(); // works
},
stop: function() {
this.parseText(); // works
},
parseText: {
load: function ()
{
this.call(); //*** dont work
instance.call(); // work, but what if i have this instance (same name) on another object, would'nt this conflict it?
}
}
};
I'm using an instance, which works fine, but what if I or someone wrote an instance (same name) var in another object, wouldn't it will conflict and overwrite this instance?
Eric's answer gives you a reasonable example of how to do what you want to do, but doesn't really go into why.
In JavaScript, this is set entirely by how a function is called (for now; see below the fold for details), not where the function is defined as it is in some other languages that have the same keyword (Java, C++, C#, ...).
You, the coder, determine what this will be each time you call a function. There are two main ways: By calling the function via an object property (in the same expression), or explicitly using the function's built-in call and apply functions.
Via an object property
Using an object property:
obj.foo(); // or
obj["foo"](); // both work
That does two very distinct things, but which collaborate to set the this value: First, the function reference is found by looking up the foo property of the object obj. Then, the function is called. Because you called it as part of the same overall expression retrieving the property value, the JavaScript engine will set this to obj within the call.
So in your example, test.parseText.load(), within the load call this will be parseText, not test, because that's the object on which load was looked up.
Note that setting-this-via-property-lookup only works when they're done at the same time. This does not work:
var f = obj.foo;
f(); // `this` will not be `obj` within the call
That doesn't work because they weren't done at the same time. The property lookup and function call were separated.
Using call or apply
The second way of setting this is more explicit: All functions have the call and apply properties, which are themselves function references that call the function using information you supply. In both cases, the first argument is the object to use as this during the call. So if we wanted to fix the example above that didn't work, we could do this:
var f = obj.foo;
f.call(obj); // `this` will be `obj` within the call
f.apply(obj); // same
The only difference between call and apply is how you supply function arguments. With call, you supply them as further discrete arguments to the function; with apply, you pass in an array of arguments.
So these all do the same thing:
// 1 - Directly via property
obj.foo("a", "b", "c");
// 2 - Using `call`
f = obj.foo;
f.call(obj, "a", "b", "c");
// 3 - Using `apply`
f = obj.foo;
f.apply(obj, ["a", "b", "c"]); // Note the `[ ... ]`, one array with three elements
You can see how call and apply could work with your existing structure:
test.parseText.load.call(test.parseText);
That calls test.parseText.load, making this = test.parseText within the call.
What Eric did in his answer was to use a closure to make it simpler for you to call parseText with the this value you expect.
Further reading (disclosure: from my blog):
Mythical methods
You must remember this
Closures are not complicated
Up top I said:
In JavaScript, this is set entirely by how a function is called
(for now...
The reason I said "for now" is that in ES6, JavaScript is getting "arrow functions" and unlike other functions, the value of this within an arrow function is set by where they're created, not how they're called: They get this from the context where you create them.
Suppose you were writing code in an object method and wanted to use another method of the object to, I don't know, output information from an array (yes, this is contrived). In ES5, you'd probably do this:
this.output("Entries:");
theArray.forEach(function(entry, index) {
this.output(index + ": " + entry);
}, this);
// ^------- tells `forEach` what to use as `this` during the callback
If you left off the argument, you'd have a bug:
this.output("Entries:");
theArray.forEach(function(entry, index) {
this.output(index + ": " + entry); // <== Bug, `this` is either
// `undefined` (strict) or
// the global object (loose)
});
But since arrow functions inherit this from where they're created rather than getting it based on how they're called, the arrow function version of that doesn't need the second argument:
this.output("Entries:");
theArray.forEach((entry, index) => {
this.output(index + ": " + entry);
});
If all you're worried about is test changing, do it like this:
var test = (function() {
var object = {}
object.call = function() {
this.stop(); // works
};
object.stop = function() {
this.parseText(); // apparently works, even though parseText is not a function
};
object.parseText = {
load: function() {
object.call(); // works
}
};
return object;
})();
If you don't know the name of test, you can use a self-invoking anonymous function to create a wrapper, and refer to the object as shown below.
Note that test is not a reference to a function, but to the return value of the anonymous function. Because the object name (obj) is wrapped inside a function, it cannot be read or modified from outside
The solution below is neat, does not pollute the scope of test, and works like a charm. As mentioned earlier, test refers to the same object as obj. It's however not possible to manipulate variable obj, from outside, so that the code inside the function breaks.
var test = (function(){ //Self-executing function
var obj = {
call: function() {
this.stop(); // works
},
stop: function() {
this.parseText(); // works
},
parseText: {
load: function ()
{
obj.call(); // obj refers to the main object
}
}
};
return obj; //Return the object, which is assigned to `test`.
})(); //Invoke function
Update
It's not possible to reliably refer to self, this, or any reference to the object inside an object, without wrapping it.
Your current solution does not work, see comments in the code below:
var obj = {
init: function(){
var instance = this; //`instance` is declared using `var` inside a function
}, // This variable cannot read from "the outside"
parseText: {
load: function(){
instance.call(); //Does NOT work! instance is not defined
}
}
}
"call" is actually a built-in function on the function object that can be used to call the function specifying what to use for this. How does your code work? It doesn't seem like it should since parseText isn't a function...
Maybe try this:
parseText: function() {
var load = function ()
{
this.call(); //*** should work
};
load.call(this);
}