让所有函数只接受对象包装的参数原语是否最有效?
Is it most efficient to have all functions accept only parameter primitives wrapped by an object?
在 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' 只是对包含在对象中的原始 'one' 和 'two' 的引用,因此不会进行复制,这样可以节省计算量吗?
当然,如果我需要操纵 'one' 和 'two' 的值并且不希望更改持续存在,我会使用第二个函数。
因此,对于 JavaScript 开发人员来说,将他们的函数参数原语封装在一个对象中(假设他们不希望操作持续存在)难道不应该始终是建议的最佳实践吗?
Therefore, it should be the case that this:
sum(one: number, two: number): number {
return one + two;
}
is always less efficient than this:
sum(input: { one: number, two: number}): number {
return input.one + input.two;
}
这不符合。
传递给函数的是其参数的值。在计算机科学的上下文中,有几种不同的方式来解释“值”,因此我将使用真正非常实用的方式:在运行时进入变量、堆栈等的位。
值非常 有效地传递给函数。您将它们压入堆栈,然后该函数将它们从堆栈中弹出。所以
sum(1, 2);
这样做:
- 将
1
压入堆栈。
- 将
2
压入堆栈。
- 调用函数,
- 弹出堆栈中的值
- 将它们相加
- 将 return 值压入堆栈
- returns
(放弃一些细节!)
在您的第二个示例中,要调用 sum
,您必须 创建一个对象:
sum({one: 1, two: 2});
所以它是这样做的:
- 为对象分配内存。
- 创建一个 属性,带有插槽以记住名称
"one"
及其值;将值 1
放入值槽。
- 创建第二个 属性,使用插槽来记住名称
"two"
及其值;将值 2
放入值槽。
- 将该对象的引用(一个值,粗略地说,它在内存中的位置)压入堆栈。
- 调用函数,它:
- 从堆栈中弹出对象引用。
- 在对象中查找 属性
"one"
并将其值放入局部变量(有趣的是,它可能会在堆栈中)。
- 在对象中查找[=99=]
"two"
并将其值放入局部变量。
- 将它们相加
- 将结果压入堆栈
- returns
所以您已经保存了一个 push/pop,但代价是分配一个对象并在其上填充两个属性,然后稍后查找这些值;所有这些都比堆栈操作更昂贵。
现在,在 JavaScript 中,我们创建了一个 lot 的发布对象,所以引擎非常擅长它。如果你有一个函数,在这个函数中传递一个对象最有意义,那么一定要这样做。 (例如:如果函数需要三个以上的信息来完成它的工作,让他们传递一个具有命名属性的对象通常比让他们记住参数的顺序更好的开发者体验,当然IDE 帮助)。
在 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' 只是对包含在对象中的原始 'one' 和 'two' 的引用,因此不会进行复制,这样可以节省计算量吗?
当然,如果我需要操纵 'one' 和 'two' 的值并且不希望更改持续存在,我会使用第二个函数。
因此,对于 JavaScript 开发人员来说,将他们的函数参数原语封装在一个对象中(假设他们不希望操作持续存在)难道不应该始终是建议的最佳实践吗?
Therefore, it should be the case that this:
sum(one: number, two: number): number { return one + two; }
is always less efficient than this:
sum(input: { one: number, two: number}): number { return input.one + input.two; }
这不符合。
传递给函数的是其参数的值。在计算机科学的上下文中,有几种不同的方式来解释“值”,因此我将使用真正非常实用的方式:在运行时进入变量、堆栈等的位。
值非常 有效地传递给函数。您将它们压入堆栈,然后该函数将它们从堆栈中弹出。所以
sum(1, 2);
这样做:
- 将
1
压入堆栈。 - 将
2
压入堆栈。 - 调用函数,
- 弹出堆栈中的值
- 将它们相加
- 将 return 值压入堆栈
- returns
(放弃一些细节!)
在您的第二个示例中,要调用 sum
,您必须 创建一个对象:
sum({one: 1, two: 2});
所以它是这样做的:
- 为对象分配内存。
- 创建一个 属性,带有插槽以记住名称
"one"
及其值;将值1
放入值槽。 - 创建第二个 属性,使用插槽来记住名称
"two"
及其值;将值2
放入值槽。 - 将该对象的引用(一个值,粗略地说,它在内存中的位置)压入堆栈。
- 调用函数,它:
- 从堆栈中弹出对象引用。
- 在对象中查找 属性
"one"
并将其值放入局部变量(有趣的是,它可能会在堆栈中)。 - 在对象中查找[=99=]
"two"
并将其值放入局部变量。 - 将它们相加
- 将结果压入堆栈
- returns
所以您已经保存了一个 push/pop,但代价是分配一个对象并在其上填充两个属性,然后稍后查找这些值;所有这些都比堆栈操作更昂贵。
现在,在 JavaScript 中,我们创建了一个 lot 的发布对象,所以引擎非常擅长它。如果你有一个函数,在这个函数中传递一个对象最有意义,那么一定要这样做。 (例如:如果函数需要三个以上的信息来完成它的工作,让他们传递一个具有命名属性的对象通常比让他们记住参数的顺序更好的开发者体验,当然IDE 帮助)。