Расширение прототипа 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
  }
});
Другие вопросы по тегам