Является ли наиболее эффективным, чтобы все функции принимали только примитивы параметров, обернутые объектом? - PullRequest
0 голосов
/ 06 марта 2020

В JavaScript (или TypeScript) объекты передаются по ссылке, в отличие от примитивов, которые копируются в функцию. Следовательно, разве это не так:

sum(one: number, two: number): number {
    return one + two;
}

всегда менее эффективен, чем этот?

sum(input: { one: number, two: number}): number {
    return input.one + input.two;
}

В первой функции выполняются 'one' и 'two' копии. Во второй функции «один» и «два» - это просто ссылки на исходные «один» и «два», заключенные в объект, поэтому копии не будут создаваться, что правильно сохраняет вычисления?

Конечно, если мне нужно будет манипулировать значениями 'one' и 'two' и не хотеть, чтобы изменения сохранялись, я бы использовал вторую функцию.

Следовательно, разве не всегда рекомендуется, чтобы JavaScript разработчики включали свои примитивы параметров функции в объект (учитывая, что они не хотят, чтобы манипуляции сохранялись)?

1 Ответ

6 голосов
/ 06 марта 2020

Следовательно, должно быть так, что это:

sum(one: number, two: number): number {
    return one + two;
}

всегда менее эффективно, чем это:

sum(input: { one: number, two: number}): number {
    return input.one + input.two;
}

Это не следует.

В функцию передаются значения ее аргументов. Существует несколько различных способов интерпретации «значения» в этом контексте в компьютерных науках, поэтому я буду использовать действительно, действительно прагматический c один: биты, которые go в переменной, в стеке, и т. Д. c. во время выполнения.

Значения чрезвычайно эффективны для передачи функциям. Вы кладете sh их в стек, и функция выталкивает их из стека. Так

sum(1, 2);

делает это:

  • Вставляет 1 в стек.
  • Вставляет 2 в стек.
  • Вызывает функцию, которая
    • извлекает значения из стека
    • складывает их вместе
    • помещает возвращаемое значение в стек
    • возвращает

(Отказ от руки некоторых деталей!)

Во втором примере для вызова sum необходимо создать объект :

sum({one: 1, two: 2});

, поэтому он делает это:

  • Выделяет память для объекта.
  • Создает свойство со слотами для запоминания имени "one" и значение для него; помещает значение 1 в слот значения.
  • Создает второе свойство со слотами для запоминания имени "two" и значения для него; помещает значение 2 в слот значения.
  • Помещает ссылку на этот объект (значение, приблизительно говоря, где оно находится в памяти) в стек.
  • Вызывает функцию, которая:
    • выталкивает ссылку на объект из стека.
    • ищет свойство "one" в объекте и помещает его значение в локальную переменную (которая, что забавно, вероятно будет в стеке) .
    • ищет свойство "two" в объекте и помещает его значение в локальную переменную.
    • складывает их вместе
    • помещает результат в стек
    • возвращает

Таким образом, вы сохранили один push / pop, но за счет выделения объекта и заполнения двух свойств, а затем поиска этих значений потом; все это дороже, чем операция со стеком.

Теперь, в JavaScript, мы создаем объекты релиза lot , поэтому движки очень хороши в этом. Если у вас есть функция, в которой наиболее целесообразно передать объект, непременно сделайте это. (Например: если для выполнения своей работы функции требуется более трех частей информации, разработчикам часто лучше передать их объекту с именованными свойствами, чем запоминать порядок параметров, хотя, конечно, IDE помогают).

...