Skip to content

@cowboy /call-invo-cursion.js
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
JavaScript: call invo-cursion?
// OOP
console.log( 'OHAI'.blink() );
// Call invocation
console.log( String.prototype.blink.call('OHAI') );
// $ always makes things look awesome.
var $ = Function.prototype.call;
// Very explicit call invocation
console.log( $.call(String.prototype.blink, 'OHAI') );
// Very, very explicit call invocation, ie. call invo-cursion?
console.log( $.call($,$,$,$,$,$,$,$,$,$,$,$, String.prototype.blink, 'OHAI') );
// ^^^^^^^^^^^^^^^^^^^^^^^ "bonus" calls
// You can have fun with apply invocation and _ too.
var _ = Function.prototype.apply;
// Very, very explicit apply invocation, ie. apply invo-cursion.
console.log( _.apply(_,[_,[_,[_,[_,[_,[_,[_, [ String.prototype.blink, ['OHAI'] ]]]]]]]]) );
// ^^^^^^^^^^^^^^^^^^^^^^ "bonus" applies, and fun w/brackets ^^^^^^^^
@ricardobeat

That enables a very easy way to create number lists:

$.call(_, Array, 0, new Array(5)).map($, parseInt)
// 0, 1, 2, 3, 4
@cowboy
Owner

@ricardobeat I had no idea that Array.apply(null, new Array(5)) would return a non-sparse array. Very cool!

@cowboy
Owner

Also @ricardobeat, I'd probably do something more like this (just in general) to create a number list:

Array.apply(null, {length: 5}).map(Number.call, Number) // [0, 1, 2, 3, 4]
@cowboy
Owner

In the vein of .map(Number.call, Number) this function will swallow n leading function arguments:

function swallow(n, fn) {
  return n ? swallow(n - 1, fn.call.bind(fn)) : fn;
}

function log(a, b, c) {
  console.log([a, b, c]);
}

log(6, 7, 8)              // [ 6, 7, 8 ]

swallow(1, log)(6, 7, 8)  // [ 7, 8, undefined ]
swallow(2, log)(6, 7, 8)  // [ 8, undefined, undefined ]
swallow(3, log)(6, 7, 8)  // [ undefined, undefined, undefined ]
@Ivanca

In that way of creating number lists it can be misleading to write Number.call, I would suggest to point to a more generic location like the Function constructor:

Array.apply(null, {length: 5}).map(Function.call, Number) // [0, 1, 2, 3, 4]

So its more explicit that you can use any other function:

Array.apply(null, {length: 5}).map(Function.call, Math.exp) // [1, 2.71, 7.38, 20.08, 54.59]

But if you need the numbers as strings and performance is a priority you are better off using Object.keys instead of the String constructor:

keys(Array.apply(null, {length: 5})) // ["0", "1", "2", "3", "4"]
@cowboy
Owner

@AltIvan while using a more generically-located Function#call isn't a bad idea, Function.call is no more generic than Number.call as both Function and Number are constructor functions. What you meant to suggest was Function.prototype.call which is the prototype object on which Function#call is actually defined.

Array.apply(null, {length: 5}).map(Function.prototype.call, Number) // [0, 1, 2, 3, 4]

That being said, it's a moot point, as Number.call Function.call and Function.prototype.call are all references to the same function.

Also:

// Indices as strings.
Array.apply(null, {length: 5}).map(String.call, String) // ["0", "1", "2", "3", "4"]
// Number list.
Object.keys(Array.apply(null, {length: 5})).map(Number) // [0, 1, 2, 3, 4]
@davidmarkclements

on very old/obscure versions of webkit

Array.apply(null, {length: N}) 

may not work, returns something like

[object Object] is not a valid argument for Function.prototype.apply

However, on the old/obscure version I'm testing on (id's itself as Safari 5.x but it isn't),

Array.apply(null, Array(n)) 

does work.

----EDIT-----
{length: N} also seems to fail in PhantomJS, whereas Array(N) doesn't

@vsternbach

Hey, cool stuff, but can someone please explain me how's new Array(5) is equivalent to {length: 5}, and where's {length: 5} coming from in terms of Array constructor parameters if understand this right?

@davidlinse

Regarding Array(n):

When Array is called as a function rather than as a constructor,
it creates and initialises a new Array 

taken with courtesy from Annotated ECMAScript 5.1

@luizfilipe

@vsternbach {length: 5} is an array-like for apply function

From MDN docs:

Syntax

fun.apply(thisArg, [argsArray])

Parameters

thisArg
The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.
argsArray
An array-like object, specifying the arguments with which fun should be called, or null or undefined if no arguments should be provided to the function. Starting with ECMAScript 5 these arguments can be a generic array-like object instead of an array. See below for browser compatibility information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.