2015-03-13 4 views
4

В скриптах приложений Google У меня есть один одномерный массив данных, который я могу получить значения из так:Продлить объект JavaScript с помощью функции по умолчанию

data[0] 

Я хотел бы быть в состоянии пройти в колонке name вместо этого вот так:

data("A") 

Таким образом, мне не нужно преобразовывать буквы в их позицию в массиве. Поэтому я хотел бы расширить объект массива (расширение не является рискованным, так как оно работает в изолированной среде сценария).

Я знаю, что могу добавить функцию к прототипу массива, используя этот letter to number function и это object extension question так:

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"));

Но это немного громоздким вызова синтаксис, чем я хотел.

На основе этого вопроса на default functions, похоже, что можно назначить функцию по умолчанию для объекта, но они делают это, просто создав объект функции вроде этого:

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

Могу ли я получить расширить массив так, чтобы он выполнял функцию по умолчанию при вызове как метод?

+1

Вы не можете создать что-то, что является как массивом, так и функцией. Нужно ли вам быть массивом? Похоже, что вы хотите, это обычный объект. – JLRishe

+0

@JLRishe, это не * требуется *, чтобы быть массивом, но это то, что наиболее удобно, поскольку это то, что возвращается ['getValues'] (https://developers.google.com/apps-script/reference/spreadsheet/ диапазон # GetValues ​​()). Возможно, я мог бы обернуть все это в объект, но я думаю, что это интересная проблема. – KyleMit

+0

@ t.niese, он запускается на сервере сценариев Google Apps, который обеспечивает среду выполнения для javascript. Но он имеет довольно узкую область. Я только упоминал об этом, чтобы хеджировать комментарии, которые выступали против распространения объектов, которые у меня нет. Меня это не так беспокоит. – KyleMit

ответ

3

Проще говоря, вы не можете сделать что-то в функции, если она еще не является функцией, и вы не можете действительно расширить массивы.

Что вы можете сделать, это создать функцию-оболочку, которая оборачивает массив и обеспечивает функциональность вы хотите, а также включает в себя возможность получить обратно исходный массив, если вам это нужно:

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>

+0

Черт, я просто написал почти идентичное решение! Но я не думал о 'toArray'. Красиво сделано! –

+0

@JL, отличный ответ! – KyleMit

Смежные вопросы