我应该传递一个物体还是原始物?

时间:2016-02-25 15:30:21

标签: javascript performance

考虑我需要函数中某个对象属性的值。每当我选择在函数之间传递原始值或对象时 - 我应该选择哪一个?它会影响性能吗?我知道javascript中的对象是通过引用和原语按值传递的,实际上我可以在将值传递给某个函数之前提取一个值,也可以传递一个对象并获取函数内的值。会有什么不同吗?

3 个答案:

答案 0 :(得分:2)

从表现的角度来看,没有任何区别。

给出以下功能:

function bar(y) {
    return y.x + "A";
}

function foo(x) {
    return x + "A";
}

让我们比较两者的生成代码(d8 --print_code):

kind = FUNCTION
name = foo
Instructions (size = 140)
 44  ff7510         push [rbp+0x10]
 47  48b8917b41caf2330000 REX.W movq rax,0x33f2ca417b91    ;; object: 0x33f2ca417b91 <String[1]: A>
 57  5a             pop rdx
 58  e8010efbff     call 0x2cdacea17520     ;; debug: statement 19
                                            ;; debug: position 28
                                            ;; code: BINARY_OP_IC, UNINITIALIZED (id = 7)
 63  90             nop
 64  48bb114b30dff2130000 REX.W movq rbx,0x13f2df304b11    ;; object: 0x13f2df304b11 Cell for 6144
 74  83430bd1       addl [rbx+0xb],0xd1
 78  791f           jns 111  (0x2cdacea6674f)
 80  50             push rax
 81  e82a45fdff     call InterruptCheck  (0x2cdacea3ac60)    ;; code: BUILTIN
 86  58             pop rax
 87  48bb114b30dff2130000 REX.W movq rbx,0x13f2df304b11    ;; object: 0x13f2df304b11 Cell for 6144
 97  49ba0000000000180000 REX.W movq r10,0x180000000000
107  4c895307       REX.W movq [rbx+0x7],r10
111  488be5         REX.W movq rsp,rbp      ;; debug: statement 35
                                            ;; js return

kind = FUNCTION
name = bar
Instructions (size = 164)
 44  488b4510       REX.W movq rax,[rbp+0x10]
 48  488bd0         REX.W movq rdx,rax
 51  48b9a1d742caf2330000 REX.W movq rcx,0x33f2ca42d7a1    ;; object: 0x33f2ca42d7a1 <String[1]: x>
 61  e89e00fdff     call 0x2cdacea36940     ;; debug: statement 57
                                            ;; debug: position 65
                                            ;; code: LOAD_IC, UNINITIALIZED (id = 11)
 66  50             push rax
 67  48b8917b41caf2330000 REX.W movq rax,0x33f2ca417b91    ;; object: 0x33f2ca417b91 <String[1]: A>
 77  5a             pop rdx
 78  e86d0cfbff     call 0x2cdacea17520     ;; debug: position 68
                                            ;; code: BINARY_OP_IC, UNINITIALIZED (id = 7)
 83  90             nop
 84  48bb214b30dff2130000 REX.W movq rbx,0x13f2df304b21    ;; object: 0x13f2df304b21 Cell for 6144
 94  83430bd1       addl [rbx+0xb],0xd1
 98  791f           jns 131  (0x2cdacea668e3)
100  50             push rax
101  e89643fdff     call InterruptCheck  (0x2cdacea3ac60)    ;; code: BUILTIN
106  58             pop rax
107  48bb214b30dff2130000 REX.W movq rbx,0x13f2df304b21    ;; object: 0x13f2df304b21 Cell for 6144
117  49ba0000000000180000 REX.W movq r10,0x180000000000
127  4c895307       REX.W movq [rbx+0x7],r10
131  488be5         REX.W movq rsp,rbp      ;; debug: statement 75
                                            ;; js return

如您所见,bar包含一个额外的函数调用(LOAD_IC,即点)并且还有24个汇编指令。这不是你应该担心的事情。

这是调用foo(obj.x)的代码:

48b981d712a7a60d0000 REX.W movq rcx,0xda6a712d781    ;; object: 0xda6a712d781 <String[3]: foo>
488b5627       REX.W movq rdx,[rsi+0x27]
e83a03fdff     call 0x169fb62368c0     ;; debug: statement 111
                                       ;; code: contextual, LOAD_IC, UNINITIALIZED
50             push rax
49ba214140cc39180000 REX.W movq r10,0x1839cc404121    ;; object: 0x1839cc404121 <undefined>
4152           push r10
48b9c1d712a7a60d0000 REX.W movq rcx,0xda6a712d7c1    ;; object: 0xda6a712d7c1 <String[3]: obj>
488b5627       REX.W movq rdx,[rsi+0x27]
e81a03fdff     call 0x169fb62368c0     ;; debug: position 115
                                       ;; code: contextual, LOAD_IC, UNINITIALIZED
488bd0         REX.W movq rdx,rax
48b9a1d712a7a60d0000 REX.W movq rcx,0xda6a712d7a1    ;; object: 0xda6a712d7a1 <String[1]: x>
e88803fdff     call 0x169fb6236940     ;; debug: position 118
                                       ;; code: LOAD_IC, UNINITIALIZED (id = 46)
50             push rax
4b8d1464       REX.W leaq rdx,[r12+r12*2]
488b7c2410     REX.W movq rdi,[rsp+0x10]
e8b9f7faff     call 0x169fb6215d80     ;; code: CALL_IC, DEFAULT

这是bar(obj)

8b981d7a2f60c3e0000 REX.W movq rcx,0x3e0cf6a2d781    ;; object: 0x3e0cf6a2d781 <String[3]: bar>
488b5627       REX.W movq rdx,[rsi+0x27]
e83a03fdff     call 0x35b86e8368c0     ;; debug: statement 125
                                       ;; code: contextual, LOAD_IC, UNINITIALIZED
50             push rax
49ba214160ee911c0000 REX.W movq r10,0x1c91ee604121    ;; object: 0x1c91ee604121 <undefined>
4152           push r10
48b9e1d7a2f60c3e0000 REX.W movq rcx,0x3e0cf6a2d7e1    ;; object: 0x3e0cf6a2d7e1 <String[3]: obj>
488b5627       REX.W movq rdx,[rsi+0x27]
e81a03fdff     call 0x35b86e8368c0     ;; debug: position 129
                                       ;; code: contextual, LOAD_IC, UNINITIALIZED
50             push rax
4b8d1464       REX.W leaq rdx,[r12+r12*2]
488b7c2410     REX.W movq rdi,[rsp+0x10]
e8cbf7faff     call 0x35b86e815d80     ;; code: CALL_IC, DEFAULT

答案 1 :(得分:1)

  

考虑我需要函数中某个对象属性的值。

函数是否应该知道它是对象的属性,还是只需要值?该函数是否需要设置属性,还是只需要属性值?该函数是否始终需要属性值?该函数是否需要对象的多个属性?

选择有意义的东西。

  

它对性能有影响吗?

几乎没有。

答案 2 :(得分:1)

如果有疑问,测试总是好的。我已准备好jsperf test使用与转储中使用的 georg 相同的调用来比较这两种情况。

test results

正如你所看到的那样,Gecko引擎中只存在唯一可见的差异,但我认为它仍然无关紧要,因为我们谈论的是每秒约7M - 约26M的操作。

如果您正在寻找优化措施,这不是一个值得检查的好地方。