2016-02-25 69 views
0

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

+6

一般规则:不要太担心表现,直到它成为一个可衡量的问题。首先编写对您有意义的代码。 –

+2

现代Javascript引擎在幕后进行了很多优化,您几乎无法用这样的微观优化来减少它。 – deceze

+1

除非你正在做一个循环(或多个循环)而不是最终迭代10M +次,其中包含非常少的指令,你不必担心这一点,这是太低级别没有任何影响:) – Walfrat

回答

1

考虑我需要的功能部分对象的属性的值。

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

选择任何有意义的东西。

它会影响性能吗?

几乎没有。

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 
+0

你可以添加调用('bar(o)','foo(o.x)')到代码吗? – Bergi

+0

@Bergi:已更新 – georg

1

如果有疑问,测试总是很好的。我准备了jsperf test,用于比较使用与转储一起使用的georg相同调用的两种情况。

test results

正如你所看到的唯一明显的区别存在于Gecko引擎,但我认为它仍然是微不足道的,因为我们正在谈论〜7M - 每秒26M〜操作。

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

相关问题