4

In google app scripts I have a one dimensional data array that I can get values from like this:

data[0]

I'd love to be able to pass in the column name instead like this:

data("A")

That way I don't have to convert letters into their array position. So I'd like to extend the array object (extending isn't really risky since it's running in an isolated script environment).

I know I can add a function to the array prototype using this letter to number function and this object extension question like this:

Array.prototype.byCol = function(colName) {
  return this[getColumnNumber(colName) - 1];
}

function getColumnNumber(str) {
  var out = 0, len = str.length;
  for (pos = 0; pos < len; pos++) {
    out += (str.charCodeAt(pos) - 64) * Math.pow(26, len - pos - 1);
  }
  return out;
}

var data = [1,2,3,4];

document.write(data.byCol("B"));

But this is a slightly bulkier calling syntax than I wanted.

Based on this question on default functions, it looks like it's possible to assign a default function to an object, but they're doing so by just creating a function object like this:

var test = new func(function() {
    // do something
});

Can I get extend the array so that it will execute a default function when called as a method?

5
  • 1
    You can't create something that is both an array and a function. Do you need it to be an array? It sounds like what you want is a regular object. Commented Mar 13, 2015 at 20:54
  • @JLRishe, it doesn't need to be an array, but that's what's most convenient as it's what's returned by getValues. I could probably wrap the whole thing in an object, but I think it's an interesting problem anyway. Commented Mar 13, 2015 at 20:57
  • @t.niese, it's being run on the Google Apps Script server which provides an execution environment for javascript. But it has a pretty narrow scope. I was only mentioning it to hedge against comments that advocated against extending objects I don't own. I'm not as concerned about it here. Commented Mar 13, 2015 at 20:58
  • If you don't need to support legacy browsers, you might be able to get away with using a Map. See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Mar 13, 2015 at 21:04
  • 1
    Just as a note why making an callable array won't be possible: A function is defined to have a property length and this property is writeable: no. So if build something using __proto__ or similar that has the functions of Array and is callable, you end up in an callable array that will fail to change it's length. Commented Mar 13, 2015 at 21:36

1 Answer 1

3

Put simply, you can't make something into a function if it's not already a function, and you can't really extend arrays.

What you can do is create a wrapper function that wraps an array and provides the functionality you want, and also include the ability to get back the original array if you need it:

var wrapper = (function() {
  function getColumnNumber(str) {
    return Array.prototype.reduce.call(str.toUpperCase(), function (t, c) {
        return 26 * t + c.charCodeAt(0) - 64;
    }, 0) - 1;
  }

  return function(arr) {
    return function(col, val) {
      if (arguments.length === 0) {
        return arr;
      }
      if (arguments.length > 1) {
        arr[getColumnNumber(col)] = val;
      }
      return arr[getColumnNumber(col)];
    };
  };
})();

var w = wrapper([10, 20, 30, 40, 50]);

snippet.log(w('D')); // 40

w('D', 33);          // set value

snippet.log(w('D')); // 33

w()[3] = 42;         // access underlying array directly
w().push(60);

snippet.log(w('D')); // 42
snippet.log(w('F')); // 60
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

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

1 Comment

Damn, I just wrote an almost identical solution! But I didn't think of toArray. Nicely done!

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.