How to extend built-in objects in Javascript, For example Math? - javascript

Was learning Call, Apply, Bind trio.
Then tried this:
Math.__proto__.sum = function(arg1){var res=0; for(i in arg1) res+=arg1[i]; return res; };
Math.sum([1,2,3])
//Output: "6function (arg1){var res=0; for(i in arg1) res+=arg1[i]; return res; }"
Why does this output contains function defination attached with the sum output?
How do we extend a built-in object like Math in a project with such utility methods and use it all over?
Thanks :)

This is a classic example of why you don't mess with __proto__ (unless you absolutely know what you're doing). Attaching a function to Object.prototype as an enumerable property causes it to be iterated in your for...in loop since Array extends Object. This results in the function being concatenated to your sum and coerced to a string.
If you want to add functionality to Math, for most purposes, you can just assign directly to Math:
Math.sum = function() {...}

JavaScript allows you to modify native objects:
Math.sayHello = function(friend) {
alert('Hello there ' + friend);
}
Math.sayHello('buddy');
Of course this could soon be messy when you actually redefine methods.
Math.ceil = function(x) {
return parseInt(x, 10);
}
console.log(Math.ceil(4.9));

It is better to implement a method for Math in the same manner as Math.max which take the arguments and returns a folded result.
Math.add = (...args) => args.reduce((a, b) => a + b, 0);
console.log(Math.add(1, 2, 3));
console.log(Math.add(...[7, 8, 9]));
Only ES5
Math.add = function () {
var i = arguments.length,
sum = 0;
while (i--) {
sum += arguments[i];
}
return sum;
};
console.log(Math.add(1, 2, 3));
console.log(Math.add.apply(null, [7, 8, 9]));

Related

May someone help me why my console returns only 0 when i input this data in console? [duplicate]

In PHP there is func_num_args and func_get_args, is there something similar for JavaScript?
For modern Javascript or Typescript:
class Foo {
reallyCoolMethodISwear(...args) { return args.length; }
}
function reallyCoolFunction(i, ...args) { return args[i]; }
const allHailTheLambda = (...args) => {
return args.constructor == Array;
};
const x = new Foo().reallyCoolMethodISwear(0, 1, 2, 3, 4);
const y = reallyCoolFunction(3, 0, 1, 2, 3, 4, 5, 6);
const z = allHailTheLambda(43110, "world");
console.log(x, y, z); // 5 3 true
For ancient Javascript:
Use arguments. You can access it like an array. Use arguments.length for the number of arguments.
The arguments is an array-like object (not an actual array). Example function...
function testArguments () // <-- notice no arguments specified
{
console.log(arguments); // outputs the arguments to the console
var htmlOutput = "";
for (var i=0; i < arguments.length; i++) {
htmlOutput += '<li>' + arguments[i] + '</li>';
}
document.write('<ul>' + htmlOutput + '</ul>');
}
Try it out...
testArguments("This", "is", "a", "test"); // outputs ["This","is","a","test"]
testArguments(1,2,3,4,5,6,7,8,9); // outputs [1,2,3,4,5,6,7,8,9]
The full details: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments
ES6 allows a construct where a function argument is specified with a "..." notation such as
function testArgs (...args) {
// Where you can test picking the first element
console.log(args[0]);
}
The arguments object is where the functions arguments are stored.
The arguments object acts and looks like an array, it basically is, it just doesn't have the methods that arrays do, for example:
Array.forEach(callback[, thisArg]);
Array.map(callback[, thisArg])
Array.filter(callback[, thisArg]);
Array.slice(begin[, end])
Array.indexOf(searchElement[, fromIndex])
I think the best way to convert a arguments object to a real Array is like so:
argumentsArray = [].slice.apply(arguments);
That will make it an array;
reusable:
function ArgumentsToArray(args) {
return [].slice.apply(args);
}
(function() {
args = ArgumentsToArray(arguments);
args.forEach(function(value) {
console.log('value ===', value);
});
})('name', 1, {}, 'two', 3)
result:
> value === name
> value === 1
> value === Object {}
> value === two
> value === 3
You can also convert it to an array if you prefer. If Array generics are available:
var args = Array.slice(arguments)
Otherwise:
var args = Array.prototype.slice.call(arguments);
from Mozilla MDN:
You should not slice on arguments because it prevents optimizations in
JavaScript engines (V8 for example).
As many other pointed out, arguments contains all the arguments passed to a function.
If you want to call another function with the same args, use apply
Example:
var is_debug = true;
var debug = function() {
if (is_debug) {
console.log.apply(console, arguments);
}
}
debug("message", "another argument")
Similar answer to Gunnar, with more complete example:
You can even transparently return the whole thing:
function dumpArguments(...args) {
for (var i = 0; i < args.length; i++)
console.log(args[i]);
return args;
}
dumpArguments("foo", "bar", true, 42, ["yes", "no"], { 'banana': true });
Output:
foo
bar
true
42
["yes","no"]
{"banana":true}
https://codepen.io/fnocke/pen/mmoxOr?editors=0010
Yes if you have no idea that how many arguments are possible at the time of function declaration then you can declare the function with no parameters and can access all variables by arguments array which are passed at the time of function calling.
In ES6 you can do something like this:
function foo(...args)
{
let [a,b,...c] = args;
console.log(a,b,c);
}
foo(1, null,"x",true, undefined);
Hope this helps:
function x(...args) {
console.log( {...[...args] } );
}
x({a:1,b:2}, 'test');
Output:
{ '0': { a: 1, b: 2 }, '1': 'test' }
Hope this could be the helpful code:
function lazyLoadIcons(){
for(let i = 0; i < arguments.length; i++) {
var elements = document.querySelectorAll(arguments[i]);
elements.forEach(function(item){
item.classList.add('loaded');
});
}
}
lazyLoadIcons('.simple-2col', '.ftr-blue-ad', '.btm-numb');
~ Rahul Daksh
In ES6, use Array.from:
function foo()
{
foo.bar = Array.from(arguments);
foo.baz = foo.bar.join();
}
foo(1,2,3,4,5,6,7);
foo.bar // Array [1, 2, 3, 4, 5, 6, 7]
foo.baz // "1,2,3,4,5,6,7"
For non-ES6 code, use JSON.stringify and JSON.parse:
function foo()
{
foo.bar = JSON.stringify(arguments);
foo.baz = JSON.parse(foo.bar);
}
/* Atomic Data */
foo(1,2,3,4,5,6,7);
foo.bar // "{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7}"
foo.baz // [object Object]
/* Structured Data */
foo({1:2},[3,4],/5,6/,Date())
foo.bar //"{"0":{"1":2},"1":[3,4],"2":{},"3":"Tue Dec 17 2013 16:25:44 GMT-0800 (Pacific Standard Time)"}"
foo.baz // [object Object]
If preservation is needed instead of stringification, use the internal structured cloning algorithm.
If DOM nodes are passed, use XMLSerializer as in an unrelated question.
with (new XMLSerializer()) {serializeToString(document.documentElement) }
If running as a bookmarklet, you may need to wrap the each structured data argument in an Error constructor for JSON.stringify to work properly.
References
Structure Clone CommonJS Module
JS Object Clone
MDN: Array.from()

Javascript, looping through an array and the arguments "object"

I can't get my head around this, i'm using filter to loop through an array and filter out all the integers passed as arguments ,i'm not limited in the number of arguments.
But i'm stuck here when it's about to get back to the function the value of the arguments object, at least more that once.
In my code below, obviously it's not fully working because i'm doing a return within the for…in loop, this is where i don't get how I can get the this second loop without having i re-initialised to 0…
function destroyer(arr) {
var args = arguments.length;
var arg0 = arguments[0];
var Nargs = Array.prototype.slice.call(arguments, 1);
var newArr = [];
newArr = arg0.filter(filtre);
/*Only the first argument is
filtered out,here it's the value "2",
but should filter out [2,3].
The expected result is [1,1]*/
console.log(newArr);
return newArr;
function filtre(e){
for (var i in Nargs){
return e !== Nargs[i];
}
}
}
destroyer([1, 2, 3, 1, 2, 3], 2,3);
Hope this is clear enough,
Thanks for any input !
Matth.
While rgthree provided a solution very similar to what you already had, I wanted to provide a solution that takes advantage of newer ES6 features for modern browsers. If you run this through Babel, it will result in essentially the same code as in that solution, though it will still require a shim for the includes call.
function destroyer(source, ...args) {
return source.filter(el => !args.includes(el));
}
Explanation:
...args uses the spread operator to get all but the first argument into an array named args.
We can directly return the filtered array, assuming you don't need to log it and that was just for debugging.
el => !args.includes(el) is an anonymous arrow function. Since no braces are used, it will automatically return the result of the expression.
Since args is an array, we can directly use Array.prototype.includes to check if the current element is in the arguments to be removed. If it exists, we want to remove it and thus invert the return with !. An alternative could be the following: el => args.includes(el) == false.
Since your return statement in your filtre function is always executed on the first run, it's only returning the whether the first number in Nargs is equal to the current item. Instead, you can use indexOf for full browser support (which returns the index of the item in an array, or "-1" if it's not in an array) instead of a loop (or includes, or a loop, etc. as shown further below):
function destroyer(arr) {
var args = arguments.length;
var arg0 = arguments[0];
var Nargs = Array.prototype.slice.call(arguments, 1);
var newArr = [];
function filtre(e){
return Nargs.indexOf(e) === -1;
}
newArr = arg0.filter(filtre);
console.log(newArr);
return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2,3);
If you don't need Internet Explorer support, you could use Array.includes:
function filtre(e){
return !Nargs.includes(e);
}
And finally, if you really wanted to use a loop, you would only want to filter an item (return false) once it's found otherwise allow it (return true):
function filtre(e){
for (var i = 0, l = Nargs.length; i < l; i++) {
if (e === Nargs[i])
return false;
}
return true;
}

Creating the underscore reduce function from scratch

I am working on creating my own callback functions and higher order function groups. I am stuck on replicating the underscore reduce function or ._reduce function. Can someone help me understand how it works underneath the hood it has been a few days for me and I am stumped. Here is what I have so far. Please understand I am not utilizing the underscore library, I am trying to replicate it so that I can further my understanding on higher order functions. Thanks.
var reduce = function(collection, iterator, accumulator) {
var iterator = function(startPoint, combiner){
for(var i = 0; i <combiner.length; i++){
startPoint += combiner[i];
}
return iterator(accumulator, collection);
}
A simple recursive function does the trick
// arr - some array of values
// f - the reducing function
// acc - initial value for the accumulator
function reduce(arr, f, acc) {
if (arr.length === 0)
return acc
else
return reduce(arr.slice(1), f, f(acc, arr[0]))
}
// --------------------------------------------------
// example 1:
// reduce an array of numbers using an adding function
var ex1 = reduce([1,2,3], function(acc, x) { return acc + x }, 0)
console.log(ex1)
//=> 6
// --------------------------------------------------
// example 2:
// reduce an array of pairs to a mapping object
var ex2 = reduce([['a', 1], ['b', 2], ['c', 3]], function(acc, pair) {
var key = pair[0]
var value = pair[1]
acc[key] = value
return acc
}, {})
console.log(ex2)
//=> { a: 1, b: 2, c: 3 }
As #torazaburo points out in a comment, if you can use ES6, destructuring assignment cleans up the implementation even more
// ES6
function reduce([x, ...xs], f, acc) {
if (x === undefined)
return acc
else
return reduce(xs, f, f(acc, x))
}
Or it gets super sugary sweet with arrow functions
// ES6, same as above but using arrow function and ternary expression
const reduce = ([x, ...xs], f, acc)=>
x === undefined ? acc : reduce(xs, f, f(acc, x))
The Underscore implementation does provide some other conveniences though I'm guessing these are here to maintain compatibility with native Array.prototype.reduce. I personally wouldn't implement reduce this way, but that's beside the point.
Underscore passes an iterator and arr reference to the callback function.
Underscore allows you to change the context for the callback function
Here's a revised implementation which supports these other features
// our reduce version 2.0
function reduce(collection, iterator, memo, context) {
function loop(memo, i) {
if (collection.length === i)
return memo
else
return loop(iterator.call(context, memo, collection[i], i, collection), i + 1)
}
return loop(memo, 0)
}
You can use it the same as above only now it provides more information to the callback
NOTE
I've purposefully decided not to implement a behaviour of Underscore's reduce that allows you to perform a reduction without an initial value. Supporting this behaviour results in unsafe code and should never have made it into Underscore in the first place.
It's something like it:
function reduce(array, combine, start) {
for (var i = 0; i < array.length; i++)
start = combine(start, array[i]);
return start;
}
console.log(reduce([1, 2, 3, 4], function(a, b) {
return a + b;
}, 0));
Link Reference: http://eloquentjavascript.net/05_higher_order.html
In the comments of these answers, there has been a lot of confusion between Underscore's reduce and Array.prototype.reduce. Two notes:
Underscore's reduce allows for an empty collection and no seed value. In this case, it will not throw an error but rather returns undefined. naomik has convinced me that this is not safe. For example _([]).reduce(function(a, b) { return a + b}); should either throw an error or return an empty list.
Underscore's reduce works on both objects and arrays.
Now, to my original post:
I actually did the same thing—implement the key functions from Underscore from scratch—a while back, and reduce was probably the trickiest. I think reduce is easier to grok with a non-functional reduce (credit to naomik for this):
function reduce(arr, func, seed) {
var result = seed,
len = arr.length,
i = 0;
for (; i < len; i++) {
result = func(result, arr[i])
}
return result
}
Underscore's implementation is a bit more complex, handling objects and arrays, empty collections, and an optional seed value. It also uses each instead of a for loop, since that is more functional in style. This is my implementation of Underscore's reduce:
var reduce = function(coll, func, seed) {
// `isEmpty` (not shown) handles empty arrays, strings, and objects.
// Underscore accepts an optional seed value and does not
// throw an error if given an empty collection and no seed.
if (isEmpty(coll)) {
return coll;
}
var noSeed = arguments.length < 3;
// `each` (not shown) should treat arrays and objects
// in the same way.
each(coll, function(item, i) {
if (noSeed) {
// This condition passes at most once. If it passes,
// this means the user did not provide a seed value.
// Default to the first item in the list.
noSeed = false;
seed = item;
} else {
seed = func(seed, item, i);
}
});
return seed;
};

Javascript syntax with functions

I'm not sure what this means or how to word the question correctly.
In the first example I could put the variable before the function "numbers1.forEach(...)" but in the second example I could not "num.square()"?
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
var numbers2 = [1, 2, 3, 4, 5], sum = 0;
forEach(numbers2, function(number) {
sum += number;
});
console.log(sum);
// → 15
var numbers1 = [1, 2, 3, 4, 5], sum = 0;
numbers1.forEach(function(number) {
sum += number;
});
console.log(sum);
// → 15
// this works!
But this does not work
var square = function(x) {
return x * x;
};
var num = 12;
console.log(square(num));
// → 144
console.log(num.square());
// → TypeError: undefined is not a function (line 9)
// does not work?
Thanks!
Syntax-wise, there's no "magic" happening here. You're describing two very different things.
In your first example, you're passing an Array to your own defined forEach method. In the second example, the forEach you're calling is actually a built-in method on Arrays (see MDN). If you changed your forEach to not invoke action, you'll see that yours breaks and the second one still works.
You can achieve this functionality yourself. You could add a function to Number to make your second example work (although this is not a recommended practice, as it could collide with future JavaScript features [and many other reasons] or break existing functionality):
Number.prototype.square = function() {
return this * this;
};
var num = 12;
var squared = num.square();
alert(squared);
If you remove the forEach function from your first example, it will still work, that is because the Array type has a builtin forEach function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Alternatively try to change your forEach function to each and you will see that it will no longer work.
What you are trying to do is add a new method to an existing type. This is not good practice in JavaScript.
The example with the array works because Array in JavaScript (ECMAScript5) defines a forEach function.
The example with the number doesn't work because Number doesn't define a square function. You can extend Number to include the square function like this:
Number.prototype.square = function(x) {
return this * this;
};

How can I convert the "arguments" object to an array in JavaScript?

Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
The arguments object in JavaScript is an odd wart—it acts just like an array in most situations, but it's not actually an array object. Since it's really something else entirely, it doesn't have the useful functions from Array.prototype like forEach, sort, filter, and map.
It's trivially easy to construct a new array from an arguments object with a simple for loop. For example, this function sorts its arguments:
function sortArgs() {
var args = [];
for (var i = 0; i < arguments.length; i++)
args[i] = arguments[i];
return args.sort();
}
However, this is a rather pitiful thing to have to do simply to get access to the extremely useful JavaScript array functions. Is there a built-in way to do it using the standard library?
ES6 using rest parameters
If you are able to use ES6 you can use:
Rest Parameters
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
As you can read in the link
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
If you are curious about the ... syntax, it is called Spread Operator and you can read more here.
ES6 using Array.from()
Using Array.from:
function sortArgs() {
return Array.from(arguments).sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
Array.from simply convert Array-like or Iterable objects into Array instances.
ES5
You can actually just use Array's slice function on an arguments object, and it will convert it into a standard JavaScript array. You'll just have to reference it manually through Array's prototype:
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
Why does this work? Well, here's an excerpt from the ECMAScript 5 documentation itself:
NOTE: The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the slice function can be applied successfully to a host object is implementation-dependent.
Therefore, slice works on anything that has a length property, which arguments conveniently does.
If Array.prototype.slice is too much of a mouthful for you, you can abbreviate it slightly by using array literals:
var args = [].slice.call(arguments);
However, I tend to feel that the former version is more explicit, so I'd prefer it instead. Abusing the array literal notation feels hacky and looks strange.
It's also worth referencing this Bluebird promises library wiki page that shows how to manage the arguments object into array in a way that makes the function optimizable under V8 JavaScript engine:
function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return args;
}
This method is used in favor of var args = [].slice.call(arguments);. The author also shows how a build step can help reduce the verbosity.
function sortArgs(){ return [].slice.call(arguments).sort() }
// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }
Some array methods are intentionally made not to require the target object to be an actual array. They only require the target to have a property named length and indices (which must be zero or larger integers).
[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})
Use:
function sortArguments() {
return arguments.length === 1 ? [arguments[0]] :
Array.apply(null, arguments).sort();
}
Array(arg1, arg2, ...) returns [arg1, arg2, ...]
Array(str1) returns [str1]
Array(num1) returns an array that has num1 elements
You must check number of arguments!
Array.slice version (slower):
function sortArguments() {
return Array.prototype.slice.call(arguments).sort();
}
Array.push version (slower, faster than slice):
function sortArguments() {
var args = [];
Array.prototype.push.apply(args, arguments);
return args.sort();
}
Move version (slower, but small size is faster):
function sortArguments() {
var args = [];
for (var i = 0; i < arguments.length; ++i)
args[i] = arguments[i];
return args.sort();
}
Array.concat version (slowest):
function sortArguments() {
return Array.prototype.concat.apply([], arguments).sort();
}
If you're using jQuery, the following is a good deal easier to remember in my opinion:
function sortArgs(){
return $.makeArray(arguments).sort();
}
In ECMAScript 6 there's no need to use ugly hacks like Array.prototype.slice(). You can instead use spread syntax (...).
(function() {
console.log([...arguments]);
}(1, 2, 3))
It may look strange, but it's fairly simple. It just extracts arguments' elements and put them back into the array. If you still don't understand, see this examples:
console.log([1, ...[2, 3], 4]);
console.log([...[1, 2, 3]]);
console.log([...[...[...[1]]]]);
Note that it doesn't work in some older browsers like IE 11, so if you want to support these browsers, you should use Babel.
Here is benchmark of several methods converting arguments into array.
As for me, the best solution for small amount of arguments is:
function sortArgs (){
var q = [];
for (var k = 0, l = arguments.length; k < l; k++){
q[k] = arguments[k];
}
return q.sort();
}
For other cases:
function sortArgs (){ return Array.apply(null, arguments).sort(); }
Here's a clean and concise solution:
function argsToArray() {
return Object.values(arguments);
}
// example usage
console.log(
argsToArray(1, 2, 3, 4, 5)
.map(arg => arg*11)
);
Object.values( ) will return the values of an object as an array, and since arguments is an object, it will essentially convert arguments into an array, thus providing you with all of an array's helper functions such as map, forEach, filter, etc.
I recommend using ECMAScript 6 spread operator, which will Bind trailing parameters to an array. With this solution you don't need to touch the arguments object and your code will be simplified. The downside of this solution is that it does not work across most browsers, so instead you will have to use a JS compiler such as Babel. Under the hood Babel transforms arguments into a Array with a for loop.
function sortArgs(...args) {
return args.sort();
}
If you can not use a ECMAScript 6, I recommend looking at some of the other answers such as #Jonathan Fingland
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
Lodash:
var args = _.toArray(arguments);
in action:
(function(){ console.log(_.toArray(arguments).splice(1)); })(1, 2, 3)
produces:
[2,3]
Use Array.from(), which takes an array-like object (such as arguments) as argument and converts it to array:
(function() {
console.log(Array.from(arguments));
}(1, 2, 3));
Note that it doesn't work in some older browsers like IE 11, so if you want to support these browsers, you should use Babel.
function sortArg(){
var args = Array.from(arguments); return args.sort();
}
function sortArg(){
var args = Array.from(arguments);
return args.sort();
}
console.log(sortArg('a', 'b', 1, 2, '34', 88, 20, '19', 39, 'd', 'z', 'ak', 'bu', 90));
Another Answer.
Use Black Magic Spells:
function sortArguments() {
arguments.__proto__ = Array.prototype;
return arguments.slice().sort();
}
Firefox, Chrome, Node.js, IE11 are OK.
Try using Object.setPrototypeOf()
Explanation: Set prototype of arguments to Array.prototype
function toArray() {
return Object.setPrototypeOf(arguments, Array.prototype)
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explanation: Take each index of arguments , place item into an array at corresponding index of array.
could alternatively use Array.prototype.map()
function toArray() {
return [].map.call(arguments, (_,k,a) => a[k])
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explanation: Take each index of arguments , place item into an array at corresponding index of array.
for..of loop
function toArray() {
let arr = []; for (let prop of arguments) arr.push(prop); return arr
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
or Object.create()
Explanation: Create object, set properties of object to items at each index of arguments; set prototype of created object to Array.prototype
function toArray() {
var obj = {};
for (var prop in arguments) {
obj[prop] = {
value: arguments[prop],
writable: true,
enumerable: true,
configurable: true
}
}
return Object.create(Array.prototype, obj);
}
console.log(toArray("abc", 123, {def: 456}, [0, [7, [14]]]))
Benshmarck 3 methods :
function test()
{
console.log(arguments.length + ' Argument(s)');
var i = 0;
var loop = 1000000;
var t = Date.now();
while(i < loop)
{
Array.prototype.slice.call(arguments, 0);
i++;
}
console.log(Date.now() - t);
i = 0,
t = Date.now();
while(i < loop)
{
Array.apply(null, arguments);
i++;
}
console.log(Date.now() - t);
i = 0,
t = Date.now();
while(i < loop)
{
arguments.length == 1 ? [arguments[0]] : Array.apply(null, arguments);
i++;
}
console.log(Date.now() - t);
}
test();
test(42);
test(42, 44);
test(42, 44, 88, 64, 10, 64, 700, 15615156, 4654, 9);
test(42, 'truc', 44, '47', 454, 88, 64, '#ehuehe', 10, 64, 700, 15615156, 4654, 9,97,4,94,56,8,456,156,1,456,867,5,152489,74,5,48479,89,897,894,894,8989,489,489,4,489,488989,498498);
RESULT?
0 Argument(s)
256
329
332
1 Argument(s)
307
418
4
2 Argument(s)
375
364
367
10 Argument(s)
962
601
604
40 Argument(s)
3095
1264
1260
Enjoy !
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(1, 2, 3, 4).toString();
Although rest parameters work well, if you want to continue to use arguments for some reason, consider
function sortArgs() {
return [...arguments].sort()
}
[...arguments] can be considered a sort of alternative to Array.from(arguments), which also works perfectly well.
An ES7 alternative is an array comprehension:
[for (i of arguments) i].sort()
This could be easiest if you want to process or filter the arguments prior to sorting:
[for (i of arguments) if (i % 2) Math.log(i)].sort()
function x(){
var rest = [...arguments]; console.log(rest);return
rest.constructor;
};
x(1,2,3)
I tried simple destructing technique
The Arguments object is only available inside a function body. Although you can index the Arguments Object like an array, it is not an array. It does not have any array properties other than length.
// function arguments length 5
function properties(a,b,c,d,e){
var function_name= arguments.callee.name
var arguments_length= arguments.length;
var properties_length= properties.length;
var function_from= properties.caller.name;
console.log('I am the function name: '+ function_name);
console.log('I am the function length, I am function spacific: '+ properties_length);
console.log('I am the arguments length, I am context/excution spacific: '+ arguments_length);
console.log('I am being called From: '+ function_from );
}
// arguments 3
function parent(){
properties(1,2,3);
}
//arguments length 3 because execution spacific
parent();
Although it can be indexed like an array as you can see in this example:
function add(){
var sum=0;
for(var i=0; i< arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}
console.log(add(1,2,3));
However, the Arguments object is not an array and does not have any other properties other than length.
You can convert the arguments object into an array at which point you can access the Arguments object.
There are many ways you can access the arguments object inside a function body, and these include:
you can call the Array.prototoype.slice.call method.
Array.prototype.slice.call(arguments)
function giveMeArgs(arg1,arg2){
var args = Array.prototype.slice.call(arguments);
return args
}
console.log( giveMeArgs(1,2));
you can use the array literal
[].slice.call(arguments).
function giveMeArgs(arg1,arg2){
var args = [].slice.call(arguments);
return args;
}
console.log( giveMeArgs(1,2) );
you can use Rest ...
function giveMeArgs(...args){
return args;
}
console.log(giveMeArgs(1,2))
you can use spread [...]
function giveMeArgs(){
var args = [...arguments];
return args;
}
console.log(giveMeArgs(1,2));
you can use Array.from()
function giveMeArgs(){
var args = Array.from(arguments);
return args;
}
console.log(giveMeArgs(1,2));
You can create a reusable function to do it with any arguments, the simplest one is something like this:
function sortArgs() {
return [...arguments].sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
Spread syntax can be used in ES6 and above...
But if you'd like to use something compatible with ES5 and below, you can use Array.prototype.slice.call, so you code looks like this:
function sortArgs() {
return Array.prototype.slice.call(arguments).sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
There are also few other ways to do this, for Example using Array.from or loop through the arguments and assign them to a new array...
This is a very old question, but I think I have a solution that is slightly easier to type than previous solutions and doesn't rely on external libraries:
function sortArguments() {
return Array.apply(null, arguments).sort();
}

Categories

Resources