Расширение прототипа Javascript Arrays с помощью Max/Min для поиска значений
Рассматривая различные методы поиска значений max/min в массиве Javascript, я часто вижу расширяющийся прототип самого объекта Array. Итак, имея:
var a=[22,33,44,32,1];
Array.max=function(v) {
return Math.max.apply(this,v);
};
Array.max(a); // returns 44
Однако я часто делаю как ниже:
Array.prototype.max=function() {
return Math.max.apply(this,this);
};
a.max(); // returns 44
Это позволяет мне вызывать max() без параметров для самого объекта Array. Лично я не вижу никаких проблем с этим, и я продолжаю задаваться вопросом, пропускаю ли я что-то, и у этого метода есть некоторые главные проблемы, которые я пропускаю? Безопасно ли использовать как Array.max(arrayhere)
?
РЕДАКТИРОВАТЬ: Правильно ли говорить, что в первом примере мы создаем статический метод для нативного объекта Javascript Array, а во втором примере мы расширяем прототип Arrays?
2 ответа
Правильно ли говорить, что в первом примере мы создаем статический метод для нативного объекта Javascript Array, а во втором - расширяем прототип Arrays?
Да.
Лично я не вижу никаких проблем с этим, и я продолжаю задаваться вопросом, пропускаю ли я что-то, и у этого метода есть некоторые главные проблемы, которые я пропускаю?
Некоторые люди, которые используют for in
на массивах может споткнуться max
метод. Хотя лично я думаю, что они этого заслуживают, можно быть осторожным
Безопасно ли использовать как
Array.max(arrayhere)
?
Да, это позволяет избежать проблемы перечислимости. Тем не менее, вам все еще нужно учитывать, что расширение нативных javascript имеет свои проблемы, см. Также Почему расширение нативных объектов - плохая практика?, В любом случае, если вы выбрали статический подход, размещение их на собственном объекте библиотеки ничего не усложнит.
Правильный способ сделать это с помощью Object.defineProperty
или же Object.defineProperties
, В этом случае я напишу, как это сделать с последним. * Изменить: Обратите внимание, что это не будет обрабатывать пустые массивы, как вы ожидаете. Смотрите редактирование ниже.
Object.defineProperties(Array.prototype, {
max: {
configurable: true,
enumerable: false,
value: function () {return Math.max(...this)},
writable: true
},
min: {
configurable: true,
enumerable: false,
value: function () {return Math.min(...this)},
writable: true
}
});
Тогда вы можете просто сделать:
[4, 3, 2, 1].max() // 4
[4, 3, 2, 1].min() // 1
Это не позволит никому споткнуться о for in
Гоча, так как вы устанавливаете перечисляемость этих свойств как false.
РЕДАКТИРОВАТЬ. Обработка пустых массивов
Как отмечает @MikeM в своем комментарии, задокументированное поведение Math.max()
а также Math.min()
это, вероятно, не то, что имеет больше смысла - по крайней мере, для меня -. Если вы не отправляете аргументы этим функциям, вы получаете Infinity
с разными знаками в каждом случае:
Math.max(); // -Infinity
Math.min(); // Infinity
Поэтому, если массив мы вызываем .max()
или же .min()
на пусто, мы получим, возможно, не очень разумный результат. Чтобы справиться с этим крайним случаем, решением будет:
Object.defineProperties(Array.prototype, {
max: {
configurable: true,
enumerable: false,
value: function () {
if (this.length === 0) return null; // or whatever makes more sense
return Math.max(...this)
},
writable: true
},
min: {
configurable: true,
enumerable: false,
value: function () {
if (this.length === 0) return null;
return Math.min(...this)
},
writtable: true
}
});