ãã®æçš¿ã§ã¯ãããã©ãŒãã³ã¹ãäºæ³ãããã¯ããã«äœãã³ãŒããèšè¿°ããªãæ¹æ³ã«é¢ãããã³ããæäŸããŸãã ããã¯ãV8ãšã³ãžã³ïŒNode.jsãOperaãChromiumãªã©ã§äœ¿çšïŒãäžéšã®æ©èœã®æé©åãæåŠããå Žåã«ç¹ã«åœãŠã¯ãŸããŸãã
V8ã®æ©èœ
ãã®ãšã³ãžã³ã«ã¯ã€ã³ã¿ãŒããªã¿ãŒã¯ãããŸããããéåžžãšæé©åã®2ã€ã®ç°ãªãã³ã³ãã€ã©ãŒããããŸãã ã€ãŸããJSã³ãŒãã¯åžžã«ãã€ãã£ããšããŠçŽæ¥ã³ã³ãã€ã«ããã³å®è¡ãããŸãã é«éã ãšæãïŒ ããªãã¯ééã£ãŠããŸãã ãã€ãã£ãã³ãŒãã«ã³ã³ãã€ã«ããŠããå®éã«ã¯ããã©ãŒãã³ã¹ã¯åäžããŸããã ã€ã³ã¿ããªã¿ã®äœ¿çšãåãé€ãã ãã§ãããæé©åãããŠããªãã³ãŒãã®åäœã¯é
ããªããŸãã
ããšãã°ãéåžžã®ã³ã³ãã€ã©ã§ã¯ãåŒa + bã¯æ¬¡ã®ããã«ãªããŸãã
mov eax, a mov ebx, b call RuntimeAdd
ããã¯ã察å¿ããé¢æ°ã®åŒã³åºãã§ãã aãšbãæŽæ°ã®å Žåãã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
mov eax, a mov ebx, b add eax, ebx
ãŸãããã®ãªãã·ã§ã³ã¯ãå®è¡æã«è€éãªè¿œå ã®JSã»ãã³ãã£ã¯ã¹ãåŠçããåŒã³åºããããã¯ããã«é«éã«æ©èœããŸãã èšãæããã°ãéåžžã®ã³ã³ãã€ã©ã¯æé©åãããŠããªããçã®ãã³ãŒããçæããæé©åã³ã³ãã€ã©ã¯ãããæãèµ·ããããŠãæçµçãªå€èŠ³ã«å°ããŸãã åæã«ãæé©åãããã³ãŒãã®ããã©ãŒãã³ã¹ã¯ããéåžžã®ãã³ãŒãã®ããã©ãŒãã³ã¹ã®100åã«ãªããŸãã ããããå®éã«ã¯ãJSã³ãŒããèšè¿°ããŠæé©åããããšã¯ã§ããŸããã æé©åã³ã³ãã€ã©ãåŠçãæåŠããå€ãã®ããã°ã©ãã³ã°ãã¿ãŒã³ããããŸãïŒãã®äžéšã¯æ
£çšçã§ãïŒã
ãã³ãã¬ãŒããæé©åãããŠããªãå Žåããã³ãã¬ãŒããå«ãé¢æ°å
šäœã«åœ±é¿ããããšã«æ³šæããŠãã ããã çµå±ãã³ãŒãã¯äžåºŠã«1ã€ã®é¢æ°ã§æé©åãããã·ã¹ãã ã¯æ®ãã®ã³ãŒããäœãè¡ãããç¥ããŸããïŒçŸæç¹ã§æé©åãããŠããé¢æ°ã«çµã¿èŸŒãŸããŠããªãéãïŒã
以äžã§ã¯ããã®æ©èœããæé©å解é€ã®å°çãã«åé¡ãããã»ãšãã©ã®ãã³ãã¬ãŒããèŠãŠãããŸãã ã»ãšãã©ã®å Žåãããããå€æŽããããšã¯çã«ããªã£ãŠãããã³ã³ãã€ã©ãŒããŸããŸãæ°ãããã³ãã¬ãŒããèªèããããã«ãªããšãææ¡ããããœãªã¥ãŒã·ã§ã³ãäžèŠã«ãªãå¯èœæ§ããããŸãã
1.çµã¿èŸŒã¿ããŒã«ã®äœ¿çš
ãã³ãã¬ãŒããæé©åã«ã©ã®ããã«åœ±é¿ããããå€æããã«ã¯ãNode.jsãããã€ãã®V8ãã©ã°ãšãšãã«äœ¿çšã§ããå¿
èŠããããŸãã ç¹å®ã®ãã³ãã¬ãŒãã䜿çšããŠé¢æ°ãäœæãããã¹ãŠã®çš®é¡ã®ããŒã¿åã§é¢æ°ãåŒã³åºããŠãããå
éšV8é¢æ°ãåŒã³åºããŠãã§ãã¯ãšæé©åãè¡ããŸãã
test.jsïŒ
æã¡äžãïŒ
$ node --trace_opt --trace_deopt --allow-natives-syntax test.js Function is not optimized
æ©èœããã¹ãããã«ã¯ãwithã¹ããŒãã¡ã³ããã³ã¡ã³ãåããŠåèµ·åããŸãã
$ node --trace_opt --trace_deopt --allow-natives-syntax test.js [optimizing 000003FFCBF74231 <JS Function containsWith (SharedFunctionInfo 00000000FE1389E1)> - took 0.345, 0.042, 0.010 ms] Function is optimized
éžæãããœãªã¥ãŒã·ã§ã³ãæ©èœãããã©ããã確èªããã«ã¯ãçµã¿èŸŒã¿ã®ããŒã«ãããã䜿çšããããšãéèŠã§ãã
2.ãµããŒããããŠããªãæ§æ
äžéšã®æ§é ã¯ãæé©åã§ããªãæ§æã䜿çšãããããæé©åã³ã³ãã€ã©ã«ãã£ãŠæ瀺çã«ãµããŒããããŸããã
éèŠïŒãã¶ã€ã³ãå©çšã§ããªãå Žåãå®è¡ãããªãå Žåã§ãããã¶ã€ã³ãå«ãé¢æ°ãæé©åããããšã¯ã§ããŸããã
ããšãã°ããããè¡ãã®ã¯ç¡æå³ã§ãã
if (DEVELOPMENT) { debugger; }
ãã®ã³ãŒãã¯ããããã¬ãŒåŒã®å®è¡ã«å€±æããŠããé¢æ°å
šäœã«åœ±é¿ããŸãã
çŸåšæé©åãããŠããŸããïŒ
- ãžã§ãã¬ãŒã¿ãŒé¢æ°;
- for-ofåŒãå«ãé¢æ°ã
- try-catchåŒãå«ãé¢æ°ã
- try-finallyåŒãå«ãé¢æ°ã
- è€å代å
¥æŒç®åletãå«ãé¢æ°ã
- const代å
¥æŒç®åconstãå«ãé¢æ°ã
- ãªããžã§ã¯ããªãã©ã«ãå«ãé¢æ°ã«ã¯ã__ proto __ãgetããŸãã¯set宣èšãå«ãŸããŸãã
ãããããæé©åã§ããªãïŒ
- ãããã¬ãŒåŒãå«ãé¢æ°ã
- evalïŒïŒãåŒã³åºãé¢æ°;
- åŒãå«ãé¢æ°ã
誀解ãé¿ããããã«ãé¢æ°ã«æ¬¡ã®ãããããå«ãŸããŠããå Žåããã®å
šäœã¯æé©åãããŸããã
function containsObjectLiteralWithProto() { return {__proto__: 3}; } function containsObjectLiteralWithGetter() { return { get prop() { return 3; } }; } function containsObjectLiteralWithSetter() { return { set prop(val) { this.val = val; } }; }
evalãžã®çŽæ¥ã®åŒã³åºãã¯ãç¹ã«èšåããã«å€ããŸãããªããªããããããåäœãããã®ã¯ãã¹ãŠåçã¹ã³ãŒãå
ã«ããããã§ãã
åé¿ç ïŒãããã®åŒã®äžéšã¯ãå®æãã補åã³ãŒãã§ã¯ç Žæ£ã§ããŸããã ããšãã°ãtry-finallyãŸãã¯try-catchããã æ害ãªåœ±é¿ãæå°éã«æããã«ã¯ãå°ããªæ©èœã®ãã¬ãŒã ã¯ãŒã¯ã§ããããåé¢ããå¿
èŠããããŸãã
var errorObject = {value: null}; function tryCatch(fn, ctx, args) { try { return fn.apply(ctx, args); } catch(e) { errorObject.value = e; return errorObject; } } var result = tryCatch(mightThrow, void 0, [1,2,3]);
3.åŒæ°ã䜿çšãã
é¢æ°ãæé©åããããšãäžå¯èœã«ãªãããã«ãåŒæ°ã䜿çšããå€ãã®æ¹æ³ããããŸãã ãããã£ãŠãåŒæ°ãæäœãããšãã¯ãç¹ã«æ³šæããå¿
èŠããããŸãã
3.1ã åŒæ°ãé¢æ°æ¬äœã§äœ¿çšããããšããæ¡ä»¶ã§ãæå®ããããã©ã¡ãŒã¿ãŒã®åå²ãåœãŠïŒäžå®å®ã¢ãŒãïŒã¹ããããŒã¢ãŒãïŒã®ã¿ïŒ
å
žåçãªäŸïŒ
function defaultArgsReassign(a, b) { if (arguments.length < 2) b = 5; }
ãã®å Žåããã©ã¡ãŒã¿ãŒãæ°ããå€æ°ã«ä¿åã§ããŸãã
function reAssignParam(a, b_) { var b = b_;
ãããé¢æ°ã§åŒæ°ã䜿çšããå¯äžã®æ¹æ³ã§ããå Žåãundefinedã§ãã§ãã¯ããããšã§çœ®ãæããããšãã§ããŸãã
function reAssignParam(a, b) { if (b === void 0) b = 5; }
åŒæ°ãé¢æ°ã®åŸåã§äœ¿çšãããå¯èœæ§ãé«ãå Žåãåå²ãåœãŠãå¿é
ããå¿
èŠã¯ãããŸããã
åé¡ã解決ããå¥ã®æ¹æ³ã¯ããã¡ã€ã«ãŸãã¯é¢æ°ã«å¯ŸããŠãå³å¯ãªäœ¿çšããæå¹ã«ããããšã§ãã
3.2ã æŒããããè°è«
function leaksArguments1() { return arguments; } function leaksArguments2() { var args = [].slice.call(arguments); } function leaksArguments3() { var a = arguments; return function() { return a; }; }
åŒæ°ãªããžã§ã¯ãã¯ã©ãã«ãæž¡ããŠã¯ãããŸããã
ãããã·ã¯ãå
éšé
åãäœæããããšã§å®è¡ã§ããŸãã
function doesntLeakArguments() {
ãã®å Žåãå€ãã®ã³ãŒããäœæããå¿
èŠããããããæåã«ã²ãŒã ãããããã«å€ãããã©ãããå€æããã®ãçã«ããªã£ãŠããŸãã ç¹°ãè¿ããŸãããæé©åã«ã¯å€§éã®ã³ãŒããå«ãŸããããæ確ãªã»ãã³ãã£ã¯ã¹ã䌎ããŸãã
ãã ãããããžã§ã¯ããã¢ã»ã³ããªæ®µéã«ããå Žåã¯ããœãŒã¹ãããã䜿çšããå¿
èŠã®ãªããã¯ãã䜿çšããŠãããå®çŸã§ããéåžžã®JavaScriptãšããŠãœãŒã¹ã³ãŒããä¿åã§ããŸãã
function doesntLeakArguments() { INLINE_SLICE(args, arguments); return args; }
ãã®ææ³ã¯bluebirdã§äœ¿çšããããã«ã段éã§ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
function doesntLeakArguments() { var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];} return args; }
3.3ã åŒæ°ãžã®å²ãåœãŠ
ããã¯ãäžå®å®ã¢ãŒãã§ã®ã¿å®è¡ã§ããŸãã
function assignToArguments() { arguments = 3; return arguments; }
解決ç ïŒãã®ãããªã°ãããã³ãŒããæžããªãã§ãã ããã å³æ Œã¢ãŒãã§ã¯ããã®ãããªåµé æ§ã¯æé€ã«ã€ãªãããŸãã
åŒæ°ãå®å
šã«äœ¿çšããã«ã¯ã©ãããã°ããã§ããïŒ
- arguments.lengthã䜿çšããŸãã
- åŒæ°[i]ã䜿çšããŸããããã§ãiã¯åžžã«åŒæ°å
ã®æå¹ãªæŽæ°ã€ã³ããã¯ã¹ã§ããããã®å¢çå€ã«ããããšã¯ã§ããŸããã
- .lengthãŸãã¯[i]ãªãã§åŒæ°ãçŽæ¥äœ¿çšããªãã§ãã ããã
- strictã¢ãŒãã§fn.applyïŒyãåŒæ°ïŒãé©çšã§ããŸãã ãããŠãç¹ã«.sliceã æ©èœçªå·ãé©çšãããŸãã
- é¢æ°ïŒããšãã°ãfnã$ Inject = ...ïŒããã³å¶éãããé¢æ°ïŒããšãã°ãFunctionïŒbindã®çµæïŒã«ããããã£ãè¿œå ãããšãé ãã¯ã©ã¹ãäœæãããããšã«æ³šæããŠãã ããããããã£ãŠãããã¯#applyã䜿çšããå Žåã¯å®å
šã§ã¯ãããŸããã
äžèšã®ãã¹ãŠã確èªããå ŽåãåŒæ°ã䜿çšããŠããã®ãªããžã§ã¯ãã®ã¡ã¢ãªã¯å²ãåœãŠãããŸããã
4.ã¹ã€ããã±ãŒã¹
çŸåšãswitch-caseåŒã¯æ倧128åã®ã±ãŒã¹ãã€ã³ããæã€ããšãã§ãããã®æ°ãè¶
ãããšããã®åŒãå«ãé¢æ°ãæé©åã§ããŸããã
function over128Cases(c) { switch(c) { case 1: break; case 2: break; case 3: break; ... case 128: break; case 129: break; } }
é¢æ°ã®é
åãŸãã¯if-elseã䜿çšããŠã128以å
ã®ã±ãŒã¹æ°ãä¿æããŸãã
5. For-in
For-inåŒã¯ãããã€ãã®æ¹æ³ã§é¢æ°ã®æé©åã劚ããå¯èœæ§ããããŸãã
5.1ã ããŒã¯ããŒã«ã«å€æ°ã§ã¯ãããŸãã
function nonLocalKey1() { var obj = {} for(var key in obj); return function() { return key; }; } var key; function nonLocalKey2() { var obj = {} for(key in obj); }
ããŒãäžäœã®ã¹ã³ãŒãããååŸããããäžäœã®ã¹ã³ãŒããåç
§ãããããããšã¯ã§ããŸããã æä»çã«ããŒã«ã«å€æ°ã«ããå¿
èŠããããŸãã
5.2ã iterableã¯ãåçŽãªåæå¯èœãã§ã¯ãããŸãã
5.2.1ã ãããã·ã¥ããŒãã«ãã¢ãŒãã®ãªããžã§ã¯ãïŒãæ£èŠåãªããžã§ã¯ããããèŸæžã-è£å©ããŒã¿æ§é ãããã·ã¥ããŒãã«ã§ãããªããžã§ã¯ãïŒã¯åçŽãªåæåã§ã¯ãããŸãã function hashTableIteration() { var hashTable = {"-": 3}; for(var key in hashTable); }
ããšãã°ããªããžã§ã¯ããããã·ã¥ããŒãã«ã¢ãŒãã«ããããšãã§ããŸããããšãã°ãã³ã³ã¹ãã©ã¯ã¿ãŒå€ã§ããããã£ãåçã«è¿œå ããããããããããã£ãåé€ããããæå¹ãªèå¥åã§ã¯ãªãããããã£ã䜿çšãããããå Žåãªã©ã§ããã€ãŸãããã®ãããªãªããžã§ã¯ãã䜿çšãããšãããã·ã¥ããŒãã«ã§ãããã®ããã«ãããã·ã¥ããŒãã«ã«å€ãããŸãã ãã®ãããªãªããžã§ã¯ããfor-inã«æž¡ããŠã¯ãããŸããã ãªããžã§ã¯ããããã·ã¥ããŒãã«ã¢ãŒãã§ãããã©ããã確èªããã«ã¯ãNode.jsã§--allow-natives-syntaxãã©ã°ãã¢ã¯ãã£ãã«ããŠconsole.logïŒïŒ
HasFastPropertiesïŒobjïŒïŒãåŒã³åºãããšãã§ããŸãã
5.2.2ã ãªããžã§ã¯ããããã¿ã€ããã§ãŒã³ã«åæå€ãæã€ãã£ãŒã«ãããããŸã Object.prototype.fn = function() {};
ãã®æååã¯ãåæããããã£ã«ãã¹ãŠã®ãªããžã§ã¯ãã®ãããã¿ã€ãã®ãã§ãŒã³ãæäŸããŸãïŒObject.createïŒnullïŒãé€ãïŒã ãããã£ãŠãfor-inåŒãå«ãé¢æ°ã¯ãObject.createïŒnullïŒãªããžã§ã¯ããåæããªãéããæé©åã§ããªããªããŸãã
Object.definePropertyã䜿çšãããšãåæäžå¯èœãªããããã£ãå²ãåœãŠãããšãã§ããŸãã å®è¡æã«ãããè¡ãããšã¯ãå§ãããŸããã ãããããããã¿ã€ãã®ããããã£ã®ãããªéçãªãã®ãå¹æçã«æ±ºå®ããããã«-ããã ãã§ãã
5.2.3ã ãªããžã§ã¯ãã«ã¯åæãããé
åã€ã³ããã¯ã¹ãå«ãŸããŸããé
åã€ã³ããã¯ã¹ã®ããããã£ã¯
ECMAScriptä»æ§ã§å®çŸ©ãã
ãŠãããšèšããªããã°ãªããŸããïŒ
ããããã£ã®ååïŒæååïŒã¯ãToStringïŒToUint32ïŒPïŒïŒãPãšçãããToUint32ïŒPïŒã2 32-1ã§ãªãå Žåã«ã®ã¿ãé
åã®ã€ã³ããã¯ã¹ã«ãªããŸããååãé
åã®ã€ã³ããã¯ã¹ã§ããããããã£ã¯ãèŠçŽ ãšãåŒã°ããŸããããã¯éåžžé
åã«é©çšãããŸãããéåžžã®ãªããžã§ã¯ãã¯é
åã€ã³ããã¯ã¹ãæã€ããšãã§ããŸãã
normalObj[0] = value; function iteratesOverArray() { var arr = [1, 2, 3]; for (var index in arr) { } }
for-inã䜿çšããé
åã®å埩ã¯forã䜿çšãããããé
ããfor-inãå«ãé¢æ°ã¯æé©åãããŸããã
for-inã«åçŽãªåæåã§ã¯ãªããªããžã§ã¯ããæž¡ããšãé¢æ°ã«æªåœ±é¿ãåãŒããŸãã
解決ç ïŒåžžã«Object.keysã䜿çšããforã«ãŒãã䜿çšããŠé
åãå埩åŠçããŸãã ãããã¿ã€ããã§ãŒã³ã®ãã¹ãŠã®ããããã£ãæ¬åœã«å¿
èŠãªå Žåã¯ãç¬ç«ãããã«ããŒé¢æ°ãäœæããŸãã
function inheritedKeys(obj) { var ret = []; for(var key in obj) { ret.push(key); } return ret; }
6.çµäºæ¡ä»¶ã®è€éãªããžãã¯ãŸãã¯çµäºæ¡ä»¶ãäžæ確ãªç¡éã«ãŒã
ã³ãŒããèšè¿°ãããšãã«ãã«ãŒããäœæããå¿
èŠãããããšãç解ããŠããŠããã«ãŒãã«äœãå
¥ããã¹ããããããªãå ŽåããããŸãã ãããããwhileïŒtrueïŒ{ãŸãã¯forïŒ;;ïŒ{ãå
¥åããã«ãŒãã«ãã¬ãŒã¯ãæ¿å
¥ããŸãã ãªãã¡ã¯ã¿ãªã³ã°ã®æãæ¥ãã®ã¯ãé¢æ°ã®å®è¡ãé
ãããšããŸãã¯äžè¬çã«æé©åã解é€ãããŠããããšãå€æãããšãã§ãã çç±ã¯ãå¿ããããäžæç¶æ
ã§ããå¯èœæ§ããããŸãã
ã«ãŒãåŒã®æ¡ä»¶éšåã«çµäºæ¡ä»¶ãé
眮ããããã«ã«ãŒãããªãã¡ã¯ã¿ãªã³ã°ããããšã¯ç°¡åã§ã¯ãããŸããã æ¡ä»¶ãã«ãŒãã®æåŸã®ifã¹ããŒãã¡ã³ãã®äžéšã§ãããã³ãŒããå°ãªããšã1åå®è¡ããå¿
èŠãããå Žåã¯ãã«ãŒãããªãã¡ã¯ã¿ãªã³ã°ããŠ{} whileïŒïŒ;ãå®è¡ããŸãã çµäºæ¡ä»¶ãå
é ã«ããå Žåã¯ãã«ãŒãæ¬äœã®æ¡ä»¶éšåã«é
眮ããŸãã çµäºæ¡ä»¶ãäžå€®ã«ããå Žåã¯ãã³ãŒãããããããšãã§ããŸããã³ãŒãã®äžéšãäžã®è¡ããäžã«ç§»åãããã³ã«ãã«ãŒãã®äžã®è¡ã®ã³ããŒãæ®ããŸãã æ¡ä»¶ä»ããã¹ããŸãã¯å°ãªããšãåçŽãªè«çãã¹ãã䜿çšããŠçµäºæ¡ä»¶ã確èªã§ããåŸãã«ãŒãã¯æé©å解é€ãããªããªããŸãã