9

I want to figure out if Array[] and Object[] can be replaced by Array() and Object(). Can a function prototype be stuck into arrays or objects prototype chain to make them callable. Basically I am looking for some thing like this:

// some magic with prototypes
????????????????

a = [1, 3, 4]
b = [1, 3, 4]

console.log(a[1]) // prints 3
console.log(b(1)) // prints 3

a[0] = -1
// same as
b(0, -1)

console.log(a[1], b(1)) // prints -1 -1

Thanks alot!

3
  • I think I have a solution for this, but I'm still doing research... Commented Oct 12, 2011 at 20:34
  • NO it cannot be done. Why do you want b(0, -1) ? Commented Oct 12, 2011 at 21:51
  • @ThomBlake I am. One cannot create an Array-like object that is callable. Without a proxy of course, using es:h proxies you can do pretty much anything. Commented Oct 13, 2011 at 9:20

3 Answers 3

2

You probably don't want to do this, especially in any browser. This doesn't have a lot of nice features of Array, including efficiency. That said:

function ArrayFunction (arr) {
  var f = function s (p, v) {
    if (v !== undefined) {
      s[p] = v
    }
    return s[p]
  }

  for (var i = 0; i < arr.length; i++) {
    f[i] = arr[i]
  }

  return f
}

var a = new ArrayFunction([1, 3, 4])
var b = new ArrayFunction([1, 3, 4])

b(1, 5)
a[1] //3
b[1] //5

I originally wanted to use prototypes, but objects don't inherit callableness from their prototypes.

EDIT: Fixed above to not use arguments. This version does not allow you to set a value to undefined, but that's generally not considered a good practice anyway.

Sign up to request clarification or add additional context in comments.

7 Comments

You should explain what you mean by making JavaScript engines 'very sad'. I think what you mean is that functions that use arguments are slower.
@JuanMendes Yeah, that and making the baby Jesus cry.
Wow this is some monstrosity! Its getting close to what i was looking for. I wonder if this new ArrayFunction can be made to be implicit when creating a new array or object?
@Raynos I didn't forget - I thought it was bad enough already. I wouldn't trust cloning the Array.prototype methods since it's not really an Array - if I was using this and wanted those methods, I'd write them myself.
|
2

Good question but the answer is no, because objects are not functions.

The closest you can get is this:

Array.prototype.set = function(a,b) { this[a] = b; };

Then you can do:

b.set(0, -1);

2 Comments

Yup, and I would add to that you cannot override the behavior of either a function invocation () or an indexed array access [] in JS.
well, functions are objects, anyway.
2

Javascript does not support operator overloading like that. I can't think of a way to have one variable support both [] and () access, but if you don't need [] access, you could try something like:

var weird_array = (function() {
    var data = [1,2,3];
    return function(idx, n) {
        if (arguments.length === 1)
            return data[idx];
        else if (arguments.length === 2)
            return (data[idx] = n);
    };   
})();

In this example, weird_array is not actually an array, so you cannot use []'s on it, but it is a function (wrapped around a data array). You could then do:

weird_array();  // => undefined
weird_array(0); // => 1
weird_array(1); // => 2
weird_array(2); // => 3
weird_array(3); // => undefined
weird_array(1, 5); // => 5
weird_array(1); // => 5

1 Comment

Thanks! How cool, you can build closures out of objects and objects out of closures, but staidly I need both the () and [] forms.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.