Why calling a function inside another function doesn't work? - javascript

var mult = (function(){
var cache = {};
var calculate = function(){
var a = 1;
for(var i = 0, l = arguments.length; i < l; i++){
a = a * arguments[i];
}
return a;
}
return function(){
return calculate(arguments);
}
})();
console.log(mult(1, 2));
Above is my code, I expect the mult function will give me value 2, but instead it outputs NaN. I changed the line calculate(arguments) to caculate.apply(null, arguments) and it worked. I don't know why the old code doesn't work? Why do I need to use apply in this case? What does null represent here?

Your calculate function wants separate arguments, but you passed in an array1. Using .apply spreads the content of the array for you.
1 Technically an array-like arguments object that does not inherit from Array.

Related

When I use for loop in JavaScript, Is exist all value in memory?

As I was studying closures and local variables,
I was curious to see the example below.
function myLoop() {
var result = [], i, n = 4;
for (i = 0; i < n; i++) {
result[i] = function () {
return i;
}
}
return result;
}
var l = myLoop();
var f = l[0];
console.log(f()); // undefined
I recently knew how variable allocate.
Point to a value, not a allocate.
if I declare variable,
I allocated 'string'.
and I again allocated another string
var str = 'hello';
str = 'world';
and
str -> hello,
str -> world
Because 'String' is immutable.
Result
In conclusion, I wonder what is the status in memory?
i of 'for loop' exist all value in memory?
i -> 0,
i -> 1,
i -> 2,
i -> 3
or
i = 1(..3,4) allocate?
In this case, you only have a single binding for i, one which is declared at the beginning of myLoop. Every array item in result has a function which points to that singular i. So, when myLoop returns, you've created an array of functions, all of which reference a single value, the i whose value is 4:
function myLoop() {
var result = [], i, n = 4;
for (i = 0; i < n; i++) {
result[i] = function () {
return i;
}
}
return result;
}
const arr = myLoop();
console.log(
arr[0](),
arr[1]()
);
This value will eventually be garbage collected (the variable name's link to the value it contains) once nothing can reference the arr or any of its functions anymore.
If you had used let in the for loop instead of var, you would have a separate binding for i on each iteration:
function myLoop() {
var result = [], n = 4;
for (let i = 0; i < n; i++) {
result[i] = function () {
return i;
}
}
return result;
}
const arr = myLoop();
console.log(
arr[0](),
arr[1]()
);
in which case, every iteration of the for loop would have its own i value, so there'd be 4 separate values for i in memory at the time myLoop returns. Just like above, those 4 values will continue to exist until nothing can reference them anymore, and they get garbage collected.
(Technically, there'd also be another temporary binding or two for i for the duration of the loop, created by the for loop due to the mechanics of let loop declarations, but it's near invisible to scripts and is more confusing than useful to think about in this situation)

The new inserted value is replacing all values in the array

I'm trying to store a value from a parameter to an array. Unfortunately, when I'm trying to push a value, it also changed the former value. So in the end, they all have same value but it shouldn't.
For example: I push "1". It store, but when I push "2", it replaced the "1"
Here is my code:
function Add(num) {
var numArr = [];
var count= 10;
for (var i = 0; i < count; i++) {
numArr.push(num);
}
console.log(numArr);
}
Make the array global, when it is inside the function, whenever the function is called a new array is created. when array is global this problem does not arises
var numArr = [];
function Add(num) {
var count = 10;
for (var i = 0; i < count; i++) {
numArr.push(num);
}
console.log(numArr);
}
Add(11)
Add(112)
The reason why the previous value is replaced is that with each function call you declare your array all over again, with no values in it var numArr = []. Move this definition outside this function and it should be just fine
var numArr = [];
const Add = (num) => {
var count= num;
for (let i = 0; i < count; i++) {
numArr.push(num);
}
return numArr
}
console.log(Add(10))
The problem is because you instantiate the array in every iteration of the loop. The simple fix is to pass the array in to the Add() function.
function Add(arr, num) {
var count = 10;
for (var i = 0; i < count; i++) {
arr.push(num);
}
}
var numArr = [];
Add(numArr, 999);
console.log(numArr);
You could alternatively declare the array outside of the function, but this ties the function logic to external variables which makes the point of the function entirely moot.
Also note that the function itself can be replaced with the Array.fill() method which does exactly the same thing, but is unsupported in IE:
var arr = new Array(10);
arr.fill(999);
console.log(arr);
The problem is you create new array when push new value.you can create global array and push value on it.
<script>
_glb_arr=[];
$(document).ready(function (){
Add(1);
Add(3);
console.log(_glb_arr);
});
function Add(val){
_glb_arr.push(val);
}
</script>

Arguments Array in JavaScript (ES5)

Maybe that is not my evening :/ Very simple thing, I want to give an array as parameter to a function as arguments array:
function add() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
The following works:
console.log(add(1,2,3,4,5,6));
But if I fill an array and give it as parameter, like:
var myNumbers = [];
for (var i=0; i<100; i++){
myNumbers.push(i);
}
console.log(add(myNumbers));
I get trouble. I think, I miss something important about the arguments array.
How should I change the add function, so that both possibilities can work with it?
This solution works for both situation :
function add() {
var arr= Array.prototype.slice.call(arguments);
arr = [].concat.apply([], arr);
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
Also simple solution for sum :
function add() {
var arr= Array.prototype.slice.call(arguments);
arr = [].concat.apply([], arr);
return arr.reduce(function(f, s){return f + s;}, 0);
}
The arguments object is an array-like object, but it is not an array. It is used to represent all arguments passed into the function. You have only passed in one value into the function, so your array is actually at index 0 of the arguments object.
However, there really isn't much point using arguments here unless you need to dynamically handle things without defining an explicit API. Just declare your parameter in the add function.
function add(arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
If you want to support both cases, as per your comment, you can do something like:
function add() {
var arr = [].concat.apply([], arguments);
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
Explanation of
[].concat.apply([], arguments)
[]. is shorthand for Array.prototype because it's an empty array.
concat merges two or more arrays together, or an array and values to go into the array.
arguments is not an array, but many of the prototype functions will work on it, due to some array-like characteristics of the object - indexed items and the length property.
apply calls a function with a given context (the this binding) and any number of arguments. In this case we still want to use the array as this value to be able to call concat, followed by all the arguments we passed into add. The result is simply all arguments as a proper array.
Here:
add(1,2,3,4,5,6);
...you're calling add with a series of discrete (separate) arguments, and each of them shows up in the arguments pseudo-array, 1 at arguments[0], 2 at arguments[1], etc.
But here:
add(myNumbers);
...you're calling add with one argument, which is an array. That's at arguments[0].
You'll want to write add to fit how you want to call it. If you want to call it with discrete arguments, write it the way you have. If you want to write it to accept an array, have it take a single argument and loop through that (which will be the array):
function add(args) {
// ^------------- the one argument
var sum = 0;
for (var i = 0; i < args.length; i++) {
sum += args[i];
}
return sum;
}
If you want to handle both, you could use Array.isArray (newish, but shimmable) to check the first argument to see if it's an array and either use it if it is or use arguments if it isn't:
function add(args) {
if (!Array.isArray(args)) {
args = arguments;
}
var sum = 0;
for (var i = 0; i < args.length; i++) {
sum += args[i];
}
return sum;
}
Side note: arguments isn't an array, it's just array-like.
You can use apply
add.apply(null, [1,2,3])

Use 3 arrays as function parameter in js

i want use some arrays as function parameters.
i write this code but doesn't work.
please help me
and i have no idea about number of array
function func2(x,y,z)
{
alert(x[1]);
alert(y[1]);
alert(z[1]);
}
function func1()
{
a = [1,2,3]
b = [3,4,5]
c = [5,6,7]
func2(a,b,c);
}
Your func2 function is calling itself. Also, using var is a good idea here to avoid accidentally creating global variables:
function func2()
{
var a = [1,2,3],
b = [3,4,5],
c = [5,6,7];
func1(a,b,c);
}
Update given your updated question, if you want to create a function that accepts a variable number of parameters, you'll need to access the arguments object:
function func2()
{
alert("There are " + arguments.length + " arguments");
}
The arguments object is can be accessed just like an array (although it is not actually an array). So to print the second element from each array (remember array indexes start at 0), you'd use something like this:
function func2()
{
for (var i = 0; i < arguments.length; i++)
alert(arguments[i][1]);
}
An alternate strategy would be to just accept an array of arrays (also called a multidimensional array, though technically multidimensional arrays aren't supported in JavaScript) like this:
function func2(a)
{
for (var i = 0; i < a.length; i++)
alert(a[i][1]);
}
function func1()
{
var a = [1,2,3],
b = [3,4,5],
c = [5,6,7];
func2([a,b,c]); // notice the […] around the parameters
}
function func1(x,y,z)
{
alert(x[1]);
alert(y[1]);
alert(z[1]);
}
function func2()
{
var a = [1,2,3];
var b = [3,4,5];
var c = [5,6,7];
func1(a,b,c);
}
If I read you minds well, you have to use arguments in order to iterate over a dynamic number of arguments. Assuming you pass only arrays to func2:
function func2() {
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i][1]);
}
}

How to use the "this" keyword to call a

How do I write a function in JavaScript that receives an array and a function(convertFunc). The function calls convertFunc for every element of the array.
The element should be accessed via the this keyword.
The function should return an array of the return values of the convertFunc calls?
e.g.
function(array, convertFunc() { // array=[1,2,3]
return this+10;
}
Should return [11,12,13]
Thanks
Create the function, e.g. function map(arr, convertFunc) {
Iterate over all elements of the array arr.
Tip: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/call
Return an array containing all results from the function calls.
}
Figure the exact details out by yourself, good luck :)
array.map(callback[, thisObject]); might fit for you.
Example:
var nums = [1,2,3];
function FuncName(x)
{
return x+10;
}
var result = nums.map(FuncName); //[11,12,13]
Try this if you are looking for extending the Array object
Array.prototype.convertFunc = function() {
var arr = this, i; // As you want array is access using the this keyword.
for(i = 0; i<arr.length; i++)
{
arr[i] = arr[i] + 10;
}
return arr;
}
var myArray = [1,2,3];
// Call like this
myArray.convertFunc();
Fiddle here http://jsfiddle.net/PYxzj/
Update
And to answer your question try this
// Pass your array and a function as parameter
function arrayModify(array, convertFunc)
{
return array.convertFunc();
}
// This function iterates your array and adds 10 to each element.
var arrayAddFunction = function() {
var arr = this, i;
for(i = 0; i<arr.length; i++)
{
arr[i] = arr[i] + 10;
}
return arr;
}
// Extending the array object
Array.prototype.convertFunc = arrayAddFunction;
var aa = [1,2,3];
// As you want send your array and a function as parameters to another function
alert(arrayModify(aa,arrayAddFunction)); // -> [11, 12, 13]
Fiddle here http://jsfiddle.net/qzB4e/
var myFunc = function(fn) { // array=[1,2,3]
return fn(this);
};
myFunc.call(arr,function convertFunc(){
return this+10;
});
But, to solve your exact problem:
var arr = [1,2,3], addTen = function(){
for (var l=this.length;l--;) this[l] += 10;
};
addTen.call(arr);

Categories