i.e. is there any way to accommodate an argument, e.g. the string, if a function is invoked like so: foo('str') while written like so:
function foo(){
console.log(<the_argument>)
}
console.log(foo('str')) // <--- 'str'
You can use "arguments" keyword to get the arguments provided in foo('str'). For ex.
function foo(){
var arg = arguments; // contains array of arguments provided
console.log(arg[0]);
}
console.log(foo('str')); // prints "str"
You can use the arguments object to do the same:
function foo() {
if(arguments.length >0) {
return arguments[0];
}
}
console.log(foo('str'));
Additional info:
ES6 brings in Rest parameters & Spread syntax which help when working with functions
Arguments passed to a JS function can be retrieved by using the arguments array inside the function.
function func1(a, b, c) {
console.log(arguments[0]);
// expected output: 1
console.log(arguments[1]);
// expected output: 2
console.log(arguments[2]);
// expected output: 3
}
func1(1, 2, 3);
For more information please refer to the Mozilla documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
Yes there is. There is an implicit arguments local variable. It is iterable and can be used like an array (although it isn't an array) to access all the function's arguments without relying on any formal parameters.
function foo()
{
for (i in arguments)
{
console.log(arguments[i]);
}
}
foo('str','wasdf',9)
See Arguments object, for a more detailed definition.
Obviously not. You can check your self. If you are in angular side then you have something call DI and you can have service injected.
But you can do like make variable outside and access inside a function. If you see fit, you can test it.
Actually, you can do it, check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
Related
Kindly I am a beginner in JavaScript world, and I have a question with the below simple example,
function myFun(){
return arguments;
}
var myVar=myFun("a","b","c");
//1
console.log(myVar); //=>//["a", "b", "c", callee: function, Symbol(Symbol.iterator): function]
//2
for(m in myVar){
console.log(m); //will generate only the realistic arguments "a","b","c".
}
According to the above snippet,
why should the first invoking generate the arguments object with the inherited properties from the Function main object, and the second will generate only the realistic arguments.
If we passed the arguments object to a second function, why should it will be passed with the realistic data only, for example
function foo(something) {
console.log(something); ///=>this will generate number 3 as parameter only, not the rest of the object
return this.a + something;
}
var obj = {
a: 2
};
var bar = function() {
return foo.apply( obj, arguments );
};
var b = bar( 3 ); // 2 3
as pointed in the line of console.log(something), it will generate only the realistic params only
The error in the next example is what is interessting:
function foo() { }
foo.apply(null, 5);
The error says (on google chrome):
CreateListFromArrayLike is called on non-object.
So apparently apply calls that function first before passing the arguments to the function, CreateListFromArrayLike will create a new object (or array) out of the provided one ignoring any non-array-like properties in the process.
Note: On mozilla firefox, it throws a different error, but I think both browsers' engines have the same way of implementing apply.
as #ibrahim mahrir comments, and this article this
I discovered that, apply will typecast the object to be an array, and this is an example,
function toArray(args) {
return Array.prototype.slice.call(args);
}
function firstFun(){
console.log(toArray(arguments));
}
firstFun("A","b");
/// this will equal, the second provided example in the question itself,
thank #ibrahim and the correct answer belongs to him.
I'm a total newbie in js, so please be gentle with me :)
I want to understand where can we use the dot operator on some variable (in this case - an array), and when we cannot.
consider the following code:
//example 1
function f1(x) {
return x*x;
}
console.log(map(f1, [1,2,3,4,5]));
console.log([1,2,3,4,5].map(f1));
//example 2
function f2(arr) {
return arr;
}
console.log(f2([1,2,3,4,5]));
console.log([1,2,3,4,5].f2());
I know the examples are rather different, but still - in example 1 both prints work (and print the same) - even when using the array.function(..) syntax, while in example 2 the second print raises an error.
basically, what is the difference between the two, and why does it work only in example 1?
and generally - can I apply this method over different variable types (numbers, booleans, etc.)?
In the first example your are using the Array.prototype.map() function.
This function can be called in 2 different ways (See the docs)
[1,2,3].map(function(x){ ... }): //In your case the callback function is *f1()*
OR
arr.map(callback, [1,2,3]);
The second example is not working because the class Array has not function called f2()
[1,2,3,4,5] is an instance of Array "class", and that "class" has map method, that's why the following is a valid code:
[1,2,3,4,5].map(f1)
map method can accept any function as a parameter, and you're passing in your f1 function. It will be executed inside map function and it's executed as a standalone function.
Array "class" doesn't have f2 method, that's why this is invalid code:
[1,2,3,4,5].f2()
Here, f2 is executed immediately and is a part of [1,2,3,4,5] object
In the first case, map is defined as both a global function and public function of the Array. You can therefore call it via map(arr) or arr.map(..)
In the second case, as you only defined f2 as a global function which means the array can't access it.
What I'm trying to say with the title is:
Is there a difference in:
argument = [arg1, arg2, arg3];
Foo.bar.apply(Foo, argument);
compared to:
Foo.bar(arg1, arg2, arg3);
Except the obvious (argument vs. non argument)?
What is the reason to use the two following different "calling" methods for the same method (bar)? I have understand that apply has to do with the calling object, but is there a difference in this case?
What is the difference between call and apply? gives a lot of info regarding apply, but I haven't found a good answer to why to pass "myself".
The longer story:
/* This is the bar method in CFoo class */
CFoo.prototype.bar = function(a,b,c) {
/*
* Magic things happen here,
* and also...
*/
if (a == "SomthingSpecial") {
this.bar(a,b);
}
}
Most of the place where bar is called it is via an global instance of CFoo.
/* In the begining... */
Foo = new CFoo();
/* Some other place */
Foo.bar("Test", 3, function(v) {
/* Some stuff */
});
/* And another place */
arr = ["Test2", 4, function(v) {
/* Other stuff */
}];
Foo.bar.apply(Foo, arr);
Edit: Explained the title a bit more. Answered in #nils answer comment.
The "and another place" code, where .apply() is used, apparently wants to use an existing array as the argument list for an invocation of the function. The only (easy) way to do that in JavaScript is with .apply.
In other words, the code has an array:
arr = ["Test2", 4, function(v) {
/* Other stuff */
}];
and wants to get the effect of
Foo.bar("Test2", 4, function(v) { ... });
That is, it wants to call Foo.bar() with the array elements as arguments. To do that, it can use .apply(), but in order to make sure that this is a reference to object Foo it passes Foo as the first parameter.
So there are two requirements that come together:
The function Foo.bar() is designed to work with a correctly-set value for this, so it must be invoked either as Foo.bar() or in some way such that Foo is used as the value of this;
For some reason, a list of arguments to be passed in to Foo.bar() has been generated or computed or whatever, and that list is in an array.
.apply() does two things:
The first argument changes the context (this) of the function call.
The second argument is an array that is applied to your function. So each value in your array will be an argument value when bar is called. That would lead to a=arr[0], b=arr[1], c=arr[2]
To demonstrate why you need to pass in Foo as your context, let's look at an example. If you were to call the following, it would fail, because this would equal null:
Foo.bar.apply(null, arr); // null instead of Foo
// in the function call...
if (a == "SomthingSpecial") {
this.bar(a,b); // this == null here
}
Alternative Approach (EcmaScript 2015)
If you can work with EcmaScript 2015 and want to avoid having to pass the context, you could use the spread operator instead:
Foo.bar(...arr); // Spreading the array with the spread operator
I am reading the Eloquent JavaScript and I got to Functional programming (chapter 6). I am confused by the following example:
show(Math.min.apply(null, [5, 6]));
function negate(func) {
return function() {
return !func.apply(null, arguments);
};
}
*Note: The show() simply prints out the output to the console on the Eloquent JavaScript website.
I don't get how the negate() function is related to the code within show(). Where is the negate() function called? I don't see that it was used anywhere in that example, or am I wrong?
The code given contains two examples. Every function has an apply method. In the first example, Math.min's apply method is used to call Math.min with the argument list [5,6]. The second example should be viewed in contrast to the preceding example in which negate is defined as
function negate(func) {
return function(x) {
return !func(x);
};
}
In that example, negate(func) returns a new function of one argument that calls func with that single argument, negates the result, and returns it. What happens if func expects more than one argument, though? That's what this example covers.
function negate(func) {
return function() {
return !func.apply(null, arguments);
};
}
In this definition, negate(func) returns a new function of an arbitrary number of arguments that calls func with the list of provided arguments, negates the result, and returns it.
That part of the book was to explain that some functions take multiple parameters, so you must call the func parameter with .apply() instead of just func(x).
The first example used NaN, which accepts one parameter. That's why it worked to use:
return !func(x);
But some functions, like Math.min, accept several parameters. Technically, when using negate, you don't know what function will be passed, and what arguments will be passed. Therefore, you can't hardcode in x being passed to func. Using .apply(), you can pass the original arguments, arguments, to the func call.
Reference:
apply: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
I've tried the following with no success:
function a(args){
b(arguments);
}
function b(args){
// arguments are lost?
}
a(1,2,3);
In function a, I can use the arguments keyword to access an array of arguments, in function b these are lost. Is there a way of passing arguments to another javascript function like I try to do?
Use .apply() to have the same access to arguments in function b, like this:
function a(){
b.apply(null, arguments);
}
function b(){
console.log(arguments); //arguments[0] = 1, etc
}
a(1,2,3);
You can test it out here.
Spread operator
The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.
ECMAScript ES6 added a new operator that lets you do this in a more practical way: ...Spread Operator.
Example without using the apply method:
function a(...args){
b(...args);
b(6, ...args, 8) // You can even add more elements
}
function b(){
console.log(arguments)
}
a(1, 2, 3)
Note This snippet returns a syntax error if your browser still uses ES5.
Editor's note: Since the snippet uses console.log(), you must open your browser's JS console to see the result - there will be no in-page result.
It will display this result:
In short, the spread operator can be used for different purposes if you're using arrays, so it can also be used for function arguments, you can see a similar example explained in the official docs: Rest parameters
The explanation that none of the other answers supplies is that the original arguments are still available, but not in the original position in the arguments object.
The arguments object contains one element for each actual parameter provided to the function. When you call a you supply three arguments: the numbers 1, 2, and, 3. So, arguments contains [1, 2, 3].
function a(args){
console.log(arguments) // [1, 2, 3]
b(arguments);
}
When you call b, however, you pass exactly one argument: a's arguments object. So arguments contains [[1, 2, 3]] (i.e. one element, which is a's arguments object, which has properties containing the original arguments to a).
function b(args){
// arguments are lost?
console.log(arguments) // [[1, 2, 3]]
}
a(1,2,3);
As #Nick demonstrated, you can use apply to provide a set arguments object in the call.
The following achieves the same result:
function a(args){
b(arguments[0], arguments[1], arguments[2]); // three arguments
}
But apply is the correct solution in the general case.
If you want to only pass certain arguments, you can do so like this:
Foo.bar(TheClass, 'theMethod', 'arg1', 'arg2')
Foo.js
bar (obj, method, ...args) {
obj[method](...args)
}
obj and method are used by the bar() method, while the rest of args are passed to the actual call.
This one works like a charm.
function a(){
b(...arguments);
}
function b(){
for(var i=0;i<arguments.length;i++){
//you can use arguments[i] here.
}
}
a(1,2,3);