Каковы некоторые причины не изменять прототипы js?

Я так часто использую определенные алгоритмы, что подумываю добавить их в прототипы своего приложения. Например, последнее значение в массиве. array.last() настолько удобен по сравнению с записью arr[arr.length -1] каждый раз, когда мне нужно последнее значение в массиве.

Я бы сделал это, когда мое приложение впервые загружается.

Object.defineProperty(Array.prototype, 'last', {
   value: function(){return this[this.length -1]} })

Есть ли функциональные причины не делать этого?


person Jeremy Gottfried    schedule 13.02.2019    source источник
comment
Что происходит, когда следующая библиотека, которую вы загружаете, также хочет добавить вспомогательную функцию, вызываемую последней, в массивы, и сигнатура их функции не совпадает с вашей собственной?   -  person zero298    schedule 14.02.2019
comment
Его можно добавить, если вы делаете это в приложении, а не в библиотеке, также делайте это как полифиллы, сначала проверьте, существует ли array.prototype.last, а затем добавьте его, если это не так. Если другая библиотека, от которой вы зависите, переопределяет основные функции, то вам, вероятно, не следует ее использовать, если только библиотека буквально не сфокусирована на переопределении определенных частей, потому что она может создавать побочные эффекты для других библиотек, а также для вашего приложения.   -  person Pavlo    schedule 14.02.2019
comment
@Pavlo Пока какой-нибудь будущий стандарт ES не укажет собственный Array.prototype.last, и библиотеки, которые вы хотите использовать, не начнут зависеть от него. И нет, вы не должны не проверять, существует ли он, вы всегда должны устанавливать свою собственную версию, поскольку это функциональность, ожидаемая вашим кодом.   -  person Bergi    schedule 14.02.2019


Ответы (1)


Да, есть причины этого не делать, одна из них сразу бросается в глаза: вы неизбежно столкнетесь с другой библиотекой, которая также считает, что легче настроить встроенные прототипы.

Рассмотрим следующее:

// my-cool-library.js

// Returns the last value in an array
Array.prototype.last = function() {
    return this[this.length - 1];
}

// some-other-cool-library.js

// Returns the last possible index of the array
Array.prototype.last = function() {
    return this.length - 1;
}

// some-consumer.js

import "my-cool-library.js";
import "some-other-cool-library.js";

const a = ["a", "b", "c"];

// You would probably expect it to print "c", but it prints 2
console.log(a.last());

Вы можете подумать, что это маловероятно, но что, если вы используете действительно большие фреймворки? Допустим, вы используете и Angular, и lodash. Не исключено, что такой огромный фреймворк, как Angular, захочет упростить жизнь, добавив некоторые вспомогательные функции к определенным прототипам объектов. Однако lodash — это библиотека с очень широкой областью действия, которая также добавляет вспомогательные функции практически для каждой операции, которую вы, возможно, захотите выполнить с коллекцией.

Очень вероятно, что обе эти библиотеки захотят использовать одни и те же краткие имена вспомогательных функций, но могут иметь разные сигнатуры функций. Внезапно становится неочевидным, как вы должны вызывать и использовать Array.prototype.last.

Вместо этого лучше использовать внедрение зависимостей и писать функции, которые принимают все аргументы, необходимые для выполнения вычислений, и не загрязняют прототип. Таким образом, вы можете решить, какая именно функция last используется и когда.

Вы также можете использовать преимущества сотрясения дерева.

Рассмотрим незагрязняющий пример:

// my-cool-library.js

// Returns the last value in an array
export function last(arr) {
    return arr[arr.length - 1];
}

// some-other-cool-library.js

// Returns the last possible index of the array
export function last(arr) {
    return arr.length - 1;
}

// some-consumer.js

import {last as myLast} from "my-cool-library.js";
import {last} from "some-other-cool-library.js";

const a = ["a", "b", "c"];

// You know that you're going to use myLast 
// and how it is going to act
console.log(myLast(a));
person zero298    schedule 13.02.2019
comment
Не уверен, почему кто-то понизил бы это. Но так как все знают, что вы не должны изменять прототип, вы неизбежно столкнетесь с другой библиотекой, это не обязательно правда. Что означает, что это нормально сделать сейчас... верно? /с - person Evan Trimboli; 14.02.2019