which is the best way to write javascript ForEach - javascript

I heard forEach require a function that get 3 parameter, what about style 4 where parameters defined it. Why it's can work?
let arr = ["A", "B", "C", "D"];
//1
function temp(value, index, arr) {
console.log(value);
}
arr.forEach(temp);
//2
arr.forEach(function(value, index, arr) {
console.log(value);
});
//3
arr.forEach((value, index, arr) => {
console.log(value);
});
//4
arr.forEach(e =>
{
console.log(e);
});

The function definition defines the names of some variables that any arguments will be passed to.
That is all.
It does not enforce the number of arguments that can be passed.
You can pass any number of arguments to any function.
Some arguments might be ignored.
function myFunction(a, b, c) {
console.log("My function with " + arguments.length + " arguments");
console.log(a, b, c);
for (var i = 0; i < arguments.length; i++) {
console.log("Argument " + i + " is " + arguments[i]);
}
}
myFunction(100);
myFunction(200, 300, 400, 500, 600, 700);
function myFunctionWhichChecks(a, b, c) {
if (arguments.length !== 3) {
throw new Error("myFunctionWhichChecks must have exactly 3 arguments");
}
console.log("My function which checks has " + arguments.length + " arguments");
}
myFunctionWhichChecks(800, 900, 1000);
myFunctionWhichChecks(800, 900, 1000, 1100);

Related

Looping limited Objects in java script [duplicate]

I have an array with alot of items, and I am creating a list of them. I was thinking of paginating the list. I wonder how can I start a forEach or for loop at some index in an array, that would be in my example the number of items in the list on each page, so that I don't need to iterate over the whole array in each loop?
arr.forEach(function (item) {
someFn(item);
})
for (var i = 0, len = arr.length; i < len; i++) {
someFn(arr[i]);
}
You could use a copy of the array, by using Array#slice
The slice() method returns a shallow copy of a portion of an array into a new array object selected from begin to end (end not included). The original array will not be modified.
array.slice(10, 20).forEach(someFn); // only for functions which respects API of forEach*
* parameters for a callback
Or you can start at a given index and end at a given index.
for (var i = 10, len = Math.min(20, arr.length); i < len; i++) {
someFn(arr[i]);
}
With
Math.min(20, arr.length)
returns a value, if the array is smaller than the given value 20. For example if the array has only index 0 ... 14, you get as result 15.
Unfortunately Array#forEach iterates over every element in the given array, but you could apply a simple condition to determine to which elements (with specified index) apply the given function.
i > 3 ? someFn(item) : null;
^ if index more than 3 - call the function
var arr = [1,2,3,4,5,6,7];
function someFn(elem){
console.log(elem);
}
arr.forEach(function(item, i) {
return i > 3 ? someFn(item) : null;
})
forEach doesn't offer that feature, no. So your choices are:
A simple for loop
Ignoring the indexes you don't want to handle (as in Kind user's answer)
Using slice (as in Nina's answer)
Writing your own function
Here's #4 as an Array.prototype extension (non-enumerable, of course; adding enumerable properties to Array.prototype breaks a lot of code); after it is a standalone version for when adding to Array.prototype isn't appropriate:
// Giving ourselves the function
Object.defineProperty(Array.prototype, "myEach", {
value: function(from, to, callback, thisArg) {
if (typeof from === "function") {
thisArg = callback;
callback = to;
to = from;
from = 0;
}
if (typeof to === "function") {
thisArg = callback;
callback = to;
to = this.length;
}
for (var n = from; n < to; ++n) {
callback.call(thisArg, this[n], n, this);
}
}
});
// Using it:
var arr = ["zero", "one", "two", "three", "four", "five", "six", "seven"];
console.log("*** From 3:");
arr.myEach(3, function(e) { console.log(e); });
console.log("*** From 3 (inclusive) to 5 (exclusive):");
arr.myEach(3, 5, function(e) { console.log(e); });
console.log("*** All:");
arr.myEach(function(e) { console.log(e); });
console.log("*** Check thisArg handling on 0-2:");
var o = {answer: 42};
arr.myEach(0, 2, function(e) {
console.log(e + " (this.answer = " + this.answer + ")");
}, o);
.as-console-wrapper {
max-height: 100% !important;
}
Again note that that's a non-enumerable property, which is vital if you ever add anything to Array.prototype (otherwise, you break a lot of code).
You wouldn't do that in a library to be consumed by others, you'd just have a standalone function:
// Giving ourselves the function
function myEach(array, from, to, callback, thisArg) {
if (typeof from === "function") {
thisArg = callback;
callback = to;
to = from;
from = 0;
}
if (typeof to === "function") {
thisArg = callback;
callback = to;
to = array.length;
}
for (var n = from; n < to; ++n) {
callback.call(thisArg, array[n], n, array);
}
}
// Using it:
var arr = ["zero", "one", "two", "three", "four", "five", "six", "seven"];
console.log("*** From 3:");
myEach(arr, 3, function(e) {
console.log(e);
});
console.log("*** From 3 (inclusive) to 5 (exclusive):");
myEach(arr, 3, 5, function(e) {
console.log(e);
});
console.log("*** All:");
myEach(arr, function(e) {
console.log(e);
});
console.log("*** Check thisArg handling on 0-2:");
var o = {answer: 42};
myEach(arr, 0, 2, function(e) {
console.log(e + " (this.answer = " + this.answer + ")");
}, o);
.as-console-wrapper {
max-height: 100% !important;
}
Thinking on what #NinaScholz commented, perhaps you can use variables and any changes would be set in those instead of changing the loop.
function someFn(item, array2){
array2.push(item, array2);
}
var arrayItems1 = [1,2,3,4,5,6,7,8,9,10];
var arrayItems2 = [];
var firstIndex = 1;
var lastIndex = 5;
var i = 0;
for (i = firstIndex; i < lastIndex; i++){
someFn(arrayItems1[i], arrayItems2);
}
alert(arrayItems2.join(' '));
You could apply some kind of implementation of the iterator pattern.
var Iterator = function (list, position) {
return {
isNext: function () {
return position + 1 < list.length;
},
isDefined: function () {
return (position < list.length && position >= 0);
},
element: function () {
return list[position];
},
position: function () {
return position;
},
moveNext: function () {
if (this.isNext()) { return Iterator(list, position + 1); }
return Iterator([], 0);
}
}
Iterator.forEach = function (action, iterator, length) {
var counter = 0;
while (counter < length && iterator.isDefined()) {
counter = counter + 1;
action(iterator.element(), iterator.position());
iterator = iterator.moveNext();
}
return iterator;
}
And then have an iterator to use for going over the list and keep the state of the last iteration over a list.
var list = [1, 3, 5, 3, 6];
var iterator = Iterator(list, 0);
iterator = Iterator.forEach(function (element, index) {
console.log(element, index);
}, iterator, 3);
//1 0
//3 1
//5 2
Iterator.forEach(function (element, index) {
console.log(element, index);
}, iterator, 5);
//3 3
//6 4
array.values() to get the iterator, .next() it and use it.
let ar=[1,2,3,4]
var _;for(let a of(_=ar.values(),_.next(),_)){
console.log(a)
}

Passing multiple/unknown number of variable(s) into JavasScript a parameter?

I'm creating a reusable function with multiple/unknown number of variable(s) and one callback.
//the number of variable will be dynamic
var a = "this is a.";
var b = "this is b.";
function callback(){
console.log('callback successful');
}
//totalUp() will be reusable function
function totalUp(allVariables, callback){
console.log('Here are the complete list: ' + allVariables + '.');
callback();
}
//how do I pass unknown number of arguments(a and b) into one parameter?
totalUp({a,b},callback);
In my code above I'm passing a and b in form of object which doesn't work.
With ES6
You can use parameter destructuring for it:
function test(callback, ...params) {
console.log(params); // ["a", "b"];
console.log('Here are the complete list: ' + params.join(", ") + '.');
}
test(callback, "a", "b");
Without ES6
function test(params, callback) {
console.log(params); // ["a", "b"];
console.log('Here are the complete list: ' + params.join(", ") + '.');
}
test(["a", "b"], callback);
let allVars = [
"this is a.",
"this is b.",
]
You can have some more variables inserted into allVars and therefore you can have an unknown number of variables.
When you pass it to the function, you have 2 options.
First one is to pass array and to use it as array
function totalUp(allVars, callback){
let allVariables;
for (let i = 0; i<allVars.length; i++) {
allVariables += allVars[i] + ", ";
}
console.log('Here are the complete list: ' + allVariables + '.');
callback();
}
As Marvin mentioned, you can also use .join() to get the all variables in the array in one string.
function totalUp(allVars, callback){
let allVariables = allVars.join(", ");
console.log('Here are the complete list: ' + allVariables + '.');
callback();
}
Second one is to pass it as an object
let allVars = {
a: "this is a.",
b: "this is b."
}
I would change the sinature of the dunction and take first the necessary callback as first parameter and then take the dynamic arguments.
function upTo(cb, ...params) {
cb(...params);
}
function cb(...params) {
params.forEach(v => console.log(v));
}
upTo(cb, 1, 2, 3);
ES5
function upTo(cb) {
cb.apply(null, Array.prototype.slice.call(arguments, 1));
}
function cb() {
Array.prototype.slice.call(arguments).forEach(function (v) { console.log(v); });
}
upTo(cb, 1, 2, 3);

how do you write the code for mybind

I found this code in a book, how do you write or define the code for mybind
var concat = function(a, b) { return a + " " + b;}
var good = mybind(concat, "good");
good("night") == "good night"
To create a new function, you can either create it yourself:
function mybind(f, a) {
return function (b) {
return f(a, b);
}
}
var concat = function(a, b) { return a + " " + b;}
var good = mybind(concat, "good");
console.log(good("night"));
or for your scenario you can use function.bind to create one for you
function mybind(f, a) {
return f.bind(null, a);
}
var concat = function(a, b) { return a + " " + b;}
var good = mybind(concat, "good");
console.log(good("night"));
Like this:
var concat = function(a, b) { return a + " " + b;}
var mybind = function (fn, arg1) {
return function (arg2) {
return fn(arg1, arg2);
};
}
var good = mybind(concat, "good");
console.log(good("night") === "good night")
The following will make your comparison return true. myBind should create a new function bound to b. that's what bind does.
var mybind = function( fn, b ) { return fn.bind(this, b); };

Avoid call function with a parameter call many times

I have this:
function myalert(x)
{
alert("hey + " x)
}
i am calling a afunction with different parameters
myalert("A");
myalert("B");
myalert("C");
myalert("A");
myalert("B");
myalert("C");
myalert("A");
myalert("B");
myalert("C");
can I avoid that ugly repetition?
update=But what if 2 parameters? How will I make the "LIST" you are talking about?
Example:
function myalert(x,y)
{
alert(y + "hey + " x )
}
myalert("A", "X");
myalert("B", "X");
How can i make a list of this?
Loop it. You can get function arguments using arguments and their count arguments.length.
function myalert()
{
var count = arguments.length;
for(var i = 0; count > i; i++) {
alert("hey + " + arguments[i]);
}
}
myalert('a', 'b', 'c'); // alerts a, alerts b, alerts c
Put all parameters in an array, then use a loop.
var params = ['A', 'B', 'C'];
for (var i = 0, l = parmas.length; i < l; i++) {
myalert(params[i]);
}
or:
['A', 'B', 'C'].forEach(function(e) {
myalert(e);
});
myalert(['A', 'B', 'C']);
function myalert(dataArray)
{
dataArray.forEach(function(e) {
alert("hey " + x);
});
}

Named parameter in Javascript without overriding the existing values

Here is the code that I got from this Named parameters in javascript:
var parameterfy = (function () {
var pattern = /function[^(]*\(([^)]*)\)/;
return function (func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);
return function () {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());
var myObject = {
first: "",
second: "",
third: ""
};
var foo = parameterfy(function (a, b, c) {
//console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
myObject.first = a;
myObject.second = b;
myObject.third = c;
console.log("first " + myObject.first + " second " + myObject.second + " third " + myObject.third);
});
foo(1, 2, 3); // gives 1, 2, 3
foo({a: 11, c: 13}); // gives 11, undefined, 13
foo({ a: 11, b:myObject.second, c: 13 }); // in order to avoid undefined, this is
Note that, in second instance of foo, I got undefined as I didn't pass b so I had to work around using third instance where I passed the current value of b.
Is there anyway to make it so that if I don't have to pass a value, for example, value of b in this case so that it still updates the given values of a and c but retains the value of b?
Something like the below may work:
var foo = parameterfy(function (a, b, c) {
//console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
if(typeof a != 'undefined'){myObject.first = a;}
if(typeof b != 'undefined'){myObject.second = b;}
if(typeof c != 'undefined'){myObject.third = c;}
console.log("first " + myObject.first + " second " + myObject.second + " third " + myObject.third);
});
Here's the named parameter standard that has been successfully used for years and you should stick with it:
function myFunction(options) {
console.log(options.first);
console.log(options.second);
console.log(options.third);
}
myFunction({
first: 1,
second: 2,
third: 3
});

Categories