#javascript #arrays #monkeypatching
#javascript #массивы #monkeypatching
Вопрос:
Я хочу выяснить, можно ли заменить Array[] и Object[] на Array() и Object() . Можно ли вставить прототип функции в цепочку прототипов массивов или объектов, чтобы сделать их вызываемыми. По сути, я ищу что-то вроде этого:
// 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
Большое спасибо!
Комментарии:
1. Я думаю, что у меня есть решение для этого, но я все еще занимаюсь исследованиями…
2. НЕТ, это невозможно сделать. Почему вы хотите
b(0, -1)
?3. @ThomBlake я. Невозможно создать массивоподобный объект, который можно вызывать. Конечно, без прокси, используя прокси es: h, вы можете делать практически все.
Ответ №1:
Вы, вероятно, не хотите этого делать, особенно в любом браузере. У этого не так много приятных функций Array, включая эффективность. Тем не менее:
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
Изначально я хотел использовать прототипы, но объекты не наследуют вызываемость от своих прототипов.
РЕДАКТИРОВАТЬ: исправлено выше, чтобы не использовать arguments
. Эта версия не позволяет вам устанавливать значение undefined
равным , но в любом случае это обычно не считается хорошей практикой.
Комментарии:
1. Вы должны объяснить, что вы имеете в виду, делая движки JavaScript «очень грустными». Я думаю, вы имеете в виду, что используемые функции
arguments
работают медленнее.2. @JuanMendes Да, это и заставляет младенца Иисуса плакать.
3. Вау, это какое-то чудовище! Это приближается к тому, что я искал. Интересно, можно ли сделать эту новую функцию ArrayFunction неявной при создании нового массива или объекта?
4. Вы нарушили
.length
и забыл клонироватьArray.prototype
методы в5. @Raynos Я не забыл — я думал, что это уже достаточно плохо. Я бы не доверял клонированию методов Array.prototype, поскольку на самом деле это не массив — если бы я использовал это и хотел эти методы, я бы написал их сам.
Ответ №2:
Хороший вопрос, но ответ отрицательный, потому что объекты не являются функциями.
Самое близкое, что вы можете получить, это:
Array.prototype.set = function(a,b) { this[a] = b; };
Затем вы можете сделать:
b.set(0, -1);
Комментарии:
1. Да, и я бы добавил к этому, что вы не можете переопределить поведение ни вызова функции
()
, ни доступа к индексированному массиву[]
в JS.2. ну, в любом случае, функции — это объекты.
Ответ №3:
Javascript не поддерживает подобную перегрузку операторов. Я не могу придумать способ, чтобы одна переменная поддерживала как [], так и () доступ, но если вам не нужен [] доступ, вы могли бы попробовать что-то вроде:
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);
};
})();
В этом примере weird_array
это на самом деле не массив, поэтому вы не можете использовать для него [], но это функция (обернутая вокруг массива данных). Затем вы могли бы сделать:
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. Спасибо! Как здорово, вы можете создавать замыкания из объектов и объекты из замыканий, но обычно мне нужны обе формы () и [] .