Showing preview only (688K chars total). Download the full file or copy to clipboard to get everything.
Repository: loverajoel/jstips
Branch: master
Commit: 44a1df45df96
Files: 296
Total size: 603.4 KB
Directory structure:
gitextract_f1dq9svt/
├── CONTRIBUTING.md
├── CONTRIBUTING_es_ES.md
├── CONTRIBUTING_zh_CN.md
├── CONTRIBUTING_zh_TW.md
├── LICENSE.md
├── POST_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
├── README.md
└── _posts/
├── en/
│ ├── angular/
│ │ ├── 2016-01-01-angularjs-digest-vs-apply.md
│ │ └── 2017-03-07-preventing-unwanted-scopes-creation-in-angularjs.md
│ ├── javascript/
│ │ ├── 2015-12-29-insert-item-inside-an-array.md
│ │ ├── 2016-01-03-improve-nested-conditionals.md
│ │ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ │ ├── 2016-01-05-differences-between-undefined-and-null.md
│ │ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ │ ├── 2016-01-07-use-strict-and-get-lazy.md
│ │ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ │ ├── 2016-01-09-template-strings.md
│ │ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ │ ├── 2016-01-11-hoisting.md
│ │ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ │ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ │ ├── 2016-01-14-fat-arrow-functions.md
│ │ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ │ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ │ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ │ ├── 2016-01-18-rounding-the-fast-way.md
│ │ ├── 2016-01-19-safe-string-concatenation.md
│ │ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ │ ├── 2016-01-21-shuffle-an-array.md
│ │ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ │ ├── 2016-01-23-converting-to-number-fast-way.md
│ │ ├── 2016-01-24-use_===_instead_of_==.md
│ │ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ │ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ │ ├── 2016-01-27-short-circuit-evaluation-in-js.md
│ │ ├── 2016-01-28-curry-vs-partial-application.md
│ │ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ │ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ │ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ │ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ │ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ │ ├── 2016-02-03-implementing-asynchronous-loops.md
│ │ ├── 2016-02-04-assignment-shorthands.md
│ │ ├── 2016-02-05-observe-dom-changes.md
│ │ ├── 2016-02-06-deduplicate-an-array.md
│ │ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ │ ├── 2016-02-08-advanced-properties.md
│ │ ├── 2016-02-09-using-json-stringify.md
│ │ ├── 2016-02-10-array-average-and-median.md
│ │ ├── 2016-02-11-preventing-unapply-attacks.md
│ │ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ │ ├── 2016-02-13-know-the-passing-mechanism.md
│ │ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ │ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ │ ├── 2016-02-16-basics-declarations.md
│ │ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ │ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ │ ├── 2016-03-03-helpful-console-log-hacks.md
│ │ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ │ ├── 2016-04-05-return-values-with-the-new-operator.md
│ │ ├── 2016-04-21-get-file-extension.md
│ │ ├── 2016-05-06-use-optional-arguments.md
│ │ ├── 2016-05-12-make-easy-loop-on-array.md
│ │ ├── 2016-08-02-copy-to-clipboard.md
│ │ ├── 2016-08-10-comma-operaton-in-js.md
│ │ ├── 2016-08-17-break-continue-loop-functional.md
│ │ ├── 2016-08-25-keyword-var-vs-let.md
│ │ ├── 2016-10-28-three-useful-hacks.md
│ │ ├── 2017-01-19-binding-objects-to-functions.md
│ │ ├── 2017-03-09-working-with-websocket-timeout.md
│ │ ├── 2017-03-12-3-array-hacks.md
│ │ ├── 2017-03-16-tapping-for-quick-debugging.md
│ │ ├── 2017-03-29-recursion-iteration-and-tail-calls-in-js.md
│ │ ├── 2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md
│ │ ├── 2017-04-05-picking-and-rejecting-object-properties.md
│ │ ├── 2017-04-11-protocols-for-the-brave.md
│ │ ├── 2017-04-24-improving-your-async-functions-with-webworkers.md
│ │ ├── 2017-06-14-closures-inside-loops.md
│ │ ├── 2017-06-14-immutable-structures-and-cloning.md
│ │ ├── 2017-06-15-looping-over-arrays.md
│ │ ├── 2017-09-01-hash-maps-without-side-effects.md
│ │ ├── 2018-11-25-creating-immutable-objects-in-native-javascript.md
│ │ ├── 2020-10-13-what-is-a-functional-inheritance.md
│ │ ├── 2020-10-15-what-is-a-currying-function.md
│ │ ├── 2020-10-20-what-is-the-temporal-dead-zone.md
│ │ ├── 2020-10-22-difference-between-target-and-currentTarget.md
│ │ ├── 2020-10-27-what-is-a-spread-operator.md
│ │ ├── 2020-11-04-what-is-a-void-operator.md
│ │ ├── 2020-11-17-what-is-the-promise-executor.md
│ │ └── 2021-02-02-what-is-the-javascript-ternary-operator.md
│ ├── more/
│ │ └── 2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md
│ └── react/
│ ├── 2016-01-02-keys-in-children-components-are-important.md
│ ├── 2017-03-27-state-to-props-maps-with-memory.md
│ ├── 2017-04-04-enhancing-react-components-composition.md
│ ├── 2017-04-10-adventurers-guide-to-react.md
│ ├── 2017-05-29-upping-performance-by-appending-keying.md
│ └── 2021-07-18-trace-the-reason-make-your-page-rerender.md
├── es_ES/
│ ├── angular/
│ │ └── 2016-01-01-angularjs-digest-vs-apply.md
│ ├── javascript/
│ │ ├── 2015-12-29-insert-item-inside-an-array.md
│ │ ├── 2016-01-03-improve-nested-conditionals.md
│ │ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ │ ├── 2016-01-05-differences-between-undefined-and-null.md
│ │ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ │ ├── 2016-01-07-use-strict-and-get-lazy.md
│ │ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ │ ├── 2016-01-09-template-strings.md
│ │ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ │ ├── 2016-01-11-hoisting.md
│ │ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ │ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ │ ├── 2016-01-14-fat-arrow-functions.md
│ │ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ │ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ │ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ │ ├── 2016-01-18-rounding-the-fast-way.md
│ │ ├── 2016-01-19-safe-string-concatenation.md
│ │ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ │ ├── 2016-01-21-shuffle-an-array.md
│ │ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ │ ├── 2016-01-23-converting-to-number-fast-way.md
│ │ ├── 2016-01-24-use_===_instead_of_==.md
│ │ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ │ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ │ ├── 2016-01-27-short-circiut-evaluation-in-js.md
│ │ ├── 2016-01-28-curry-vs-partial-application.md
│ │ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ │ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ │ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ │ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ │ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ │ ├── 2016-02-03-implementing-asynchronous-loops.md
│ │ ├── 2016-02-04-assignment-shorthands.md
│ │ ├── 2016-02-05-observe-dom-changes.md
│ │ ├── 2016-02-06-deduplicate-an-array.md
│ │ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ │ ├── 2016-02-08-advanced-properties.md
│ │ ├── 2016-02-09-using-json-stringify.md
│ │ ├── 2016-02-10-array-average-and-median.md
│ │ ├── 2016-02-11-preventing-unapply-attacks.md
│ │ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ │ ├── 2016-02-13-know-the-passing-mechanism.md
│ │ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ │ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ │ ├── 2016-02-16-basics-declarations.md
│ │ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ │ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ │ ├── 2016-03-03-helpful-console-log-hacks.md
│ │ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ │ ├── 2016-04-05-return-values-with-the-new-operator.md
│ │ ├── 2016-04-21-get-file-extension.md
│ │ ├── 2016-05-06-use-optional-arguments.md
│ │ └── 2016-05-12-make-easy-loop-on-array.md
│ └── react/
│ └── 2016-01-02-keys-in-children-components-are-important.md
├── zh_CN/
│ ├── angular/
│ │ └── 2016-01-01-angularjs-digest-vs-apply.md
│ ├── javascript/
│ │ ├── 2015-12-29-insert-item-inside-an-array.md
│ │ ├── 2016-01-03-improve-nested-conditionals.md
│ │ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ │ ├── 2016-01-05-differences-between-undefined-and-null.md
│ │ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ │ ├── 2016-01-07-use-strict-and-get-lazy.md
│ │ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ │ ├── 2016-01-09-template-strings.md
│ │ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ │ ├── 2016-01-11-hoisting.md
│ │ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ │ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ │ ├── 2016-01-14-fat-arrow-functions.md
│ │ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ │ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ │ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ │ ├── 2016-01-18-rounding-the-fast-way.md
│ │ ├── 2016-01-19-safe-string-concatenation.md
│ │ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ │ ├── 2016-01-21-shuffle-an-array.md
│ │ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ │ ├── 2016-01-23-converting-to-number-fast-way.md
│ │ ├── 2016-01-24-use_===_instead_of_==.md
│ │ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ │ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ │ ├── 2016-01-27-short-circuit-evaluation-in-js.md
│ │ ├── 2016-01-28-curry-vs-partial-application.md
│ │ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ │ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ │ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ │ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ │ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ │ ├── 2016-02-03-implementing-asynchronous-loops.md
│ │ ├── 2016-02-04-assignment-shorthands.md
│ │ ├── 2016-02-05-observe-dom-changes.md
│ │ ├── 2016-02-06-deduplicate-an-array.md
│ │ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ │ ├── 2016-02-08-advanced-properties.md
│ │ ├── 2016-02-09-using-json-stringify.md
│ │ ├── 2016-02-10-array-average-and-median.md
│ │ ├── 2016-02-11-preventing-unapply-attacks.md
│ │ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ │ ├── 2016-02-13-know-the-passing-mechanism.md
│ │ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ │ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ │ ├── 2016-02-16-basics-declarations.md
│ │ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ │ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ │ ├── 2016-03-03-helpful-console-log-hacks.md
│ │ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ │ ├── 2016-04-05-return-values-with-the-new-operator.md
│ │ ├── 2016-04-21-get-file-extension.md
│ │ ├── 2016-05-06-use-optional-arguments.md
│ │ ├── 2016-05-12-make-easy-loop-on-array.md
│ │ ├── 2016-08-02-copy-to-clipboard.md
│ │ ├── 2016-08-10-comma-operaton-in-js.md
│ │ ├── 2016-08-17-break-continue-loop-functional.md
│ │ ├── 2016-08-25-keyword-var-vs-let.md
│ │ ├── 2016-10-28-three-useful-hacks.md
│ │ ├── 2017-01-19-binding-objects-to-functions.md
│ │ ├── 2017-03-09-working-with-websocket-timeout.md
│ │ ├── 2017-03-12-3-array-hacks.md
│ │ ├── 2017-03-16-tapping-for-quick-debugging.md
│ │ ├── 2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md
│ │ └── 2017-04-05-picking-and-rejecting-object-properties.md
│ ├── more/
│ │ └── 2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md
│ └── react/
│ └── 2016-01-02-keys-in-children-components-are-important.md
└── zh_TW/
├── angular/
│ ├── 2016-01-01-angularjs-digest-vs-apply.md
│ └── 2017-03-07-preventing-unwanted-scopes-creation-in-angularjs.md
├── javascript/
│ ├── 2015-12-29-insert-item-inside-an-array.md
│ ├── 2016-01-03-improve-nested-conditionals.md
│ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ ├── 2016-01-05-differences-between-undefined-and-null.md
│ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ ├── 2016-01-07-use-strict-and-get-lazy.md
│ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ ├── 2016-01-09-template-strings.md
│ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ ├── 2016-01-11-hoisting.md
│ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ ├── 2016-01-14-fat-arrow-functions.md
│ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ ├── 2016-01-18-rounding-the-fast-way.md
│ ├── 2016-01-19-safe-string-concatenation.md
│ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ ├── 2016-01-21-shuffle-an-array.md
│ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ ├── 2016-01-23-converting-to-number-fast-way.md
│ ├── 2016-01-24-use_===_instead_of_==.md
│ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ ├── 2016-01-27-short-circiut-evaluation-in-js.md
│ ├── 2016-01-28-curry-vs-partial-application.md
│ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ ├── 2016-02-03-implementing-asynchronous-loops.md
│ ├── 2016-02-04-assignment-shorthands.md
│ ├── 2016-02-05-observe-dom-changes.md
│ ├── 2016-02-06-deduplicate-an-array.md
│ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ ├── 2016-02-08-advanced-properties.md
│ ├── 2016-02-09-using-json-stringify.md
│ ├── 2016-02-10-array-average-and-median.md
│ ├── 2016-02-11-preventing-unapply-attacks.md
│ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ ├── 2016-02-13-know-the-passing-mechanism.md
│ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ ├── 2016-02-16-basics-declarations.md
│ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ ├── 2016-03-03-helpful-console-log-hacks.md
│ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ ├── 2016-04-05-return-values-with-the-new-operator.md
│ ├── 2016-04-21-get-file-extension.md
│ ├── 2016-05-06-use-optional-arguments.md
│ ├── 2016-05-12-make-easy-loop-on-array.md
│ ├── 2016-08-02-copy-to-clipboard.md
│ ├── 2016-08-10-comma-operaton-in-js.md
│ ├── 2016-08-17-break-continue-loop-functional.md
│ ├── 2016-08-25-keyword-var-vs-let.md
│ ├── 2016-10-28-three-useful-hacks.md
│ ├── 2017-01-19-binding-objects-to-functions.md
│ ├── 2017-03-09-working-with-websocket-timeout.md
│ ├── 2017-03-12-3-array-hacks.md
│ ├── 2017-03-16-tapping-for-quick-debugging.md
│ ├── 2017-03-29-recursion-iteration-and-tail-calls-in-js.md
│ ├── 2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md
│ ├── 2017-04-05-picking-and-rejecting-object-properties.md
│ └── 2017-06-15-looping-over-arrays.md
├── more/
│ └── 2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md
└── react/
├── 2016-01-02-keys-in-children-components-are-important.md
├── 2017-03-27-state-to-props-maps-with-memory.md
├── 2017-04-04-enhancing-react-components-composition.md
└── 2017-04-10-adventurers-guide-to-react.md
================================================
FILE CONTENTS
================================================
================================================
FILE: CONTRIBUTING.md
================================================
# How to submit your tip
To submit a tip to the list, fork the repository and add your tip in a new file in the correct folder (according language). The name of the file should be `2016-xx-xx-name-of-your-tip`.
Use [this format](POST_TEMPLATE.md) when writing your tip.
### Requirements
- The tip should be readable in less than two minutes
- Adding links to other sites or videos that give more insight is welcome
- Mark JS code with ```js
- Don't mention "JavaScript" in the title (as our tips are about it anyway)
- Use backticks (`) to mark code in the **title** and/or **tip-tldr** fields. _Warning_: Both values must not start with backticks!
- How you can be rewarded: If you have a PayPal, Coinbase or another account, type the url on tip-writer-support. That's all! Now your readers will be able to grab you a beer for your knowledge.
Once your tip is ready, [issue a pull request](https://help.github.com/articles/using-pull-requests/) with this [PR template](PULL_REQUEST_TEMPLATE.md) and your tip will be reviewed (see below).
## Notes
Leave the date and the tip number as **xx**. When the PR is `ready to merge`, we will tell you the correct numbers. Please also [squash](https://davidwalsh.name/squash-commits-git) your commits.
## Tip flow
**Tip proposal** ⇒ **Tip under review** ⇒ **Tip ready to merge**
- When you send a tip, it has to pass the review process and while that happens, its status is `under review`.
- Once the tip is reviewed by 5 people and has been given the reviewer's ship it emote (:shipit:), the tip is `ready to merge`.
We are looking forward to your contribution!
================================================
FILE: CONTRIBUTING_es_ES.md
================================================
# Como enviar tu tip
Para agregar tu tip a la lista, debes forkear el repositorio y agregar tu tip en un nuevo archivos en el direcctorio correcto (de acuero el lenguage). El nombre del archivo deberia ser '2016-xx-xx-nombre-de-tu-tip'.
Utilice [este formato](https://github.com/loverajoel/jstips/blob/gh-pages/POST_TEMPLATE.md) para escribir su tip.
### Requisitos
- Su tip debe ser legible en menos de dos minutos.
- Puede añadir enlaces a otros sitios o videos que dan una visión más clara es bienvenido.
- Se marcará el código JS con ```js
- No Mencione "JavaScript" en el título (como nuestros consejos son respecto de todos modos)
- Use comillas invertidas (`) para marcar código en el campos **title** y/o **tip-tldr**. _Precaucion_: Ambos valores no deben comenzar con acentos abiertos!
Una vez que su tip está listo, [issue a pull request](https://help.github.com/articles/using-pull-requests/) con esta [PR template](https://github.com/loverajoel/jstips/blob/gh-pages/PULL_REQUEST_TEMPLATE.md) y su tip será revisado (véase más adelante).
# Notas
Deje la fecha y el número de tip con **xx**. Cuando el PR es `ready to merge`, le diremos los números correctos. Por favor, también [squash] (https://davidwalsh.name/squash-commits-git) sus confirmaciones.
# Flujo del Tip
**Tip proposal** ⇒ **Tip under review** ⇒ **Tip ready to merge**
- Cuando se envía un tip, tiene que pasar el proceso de revisión y mientras eso sucede, su estado es `under review`.
- Después de que el tip sea revisado por 5 personas y han dado (:shipit:), el tip esta `ready to merge`.
================================================
FILE: CONTRIBUTING_zh_CN.md
================================================
# 如何提交小知识
将小知识提交到本列表,`fork`此仓库(repository)然后将的小知识放到对应文件夹(根据语言)的新文件中。新文件的名字应该像`2016-xx-xx-name-of-your-tip`这样。
书写小知识时请按照[这个格式](https://github.com/loverajoel/jstips/blob/gh-pages/POST_TEMPLATE.md)。
### 要求
- 小知识可以在两分钟内阅读完。
- 增加其他网站或视频的链接提供更深讲解更佳
- 使用 ```js 标记JS代码
- 无序在标题处提及"JavaScript"(因为我们的小知识全是关于它的)
- 使用反引号(`) 标记**标题**或**tip-tldr**中的代码 ‐ _警告_:它们都不能以反引号开头
当你的小知识准备就绪了, 根据这个[PR 模板](https://github.com/loverajoel/jstips/blob/gh-pages/GIT_TEMPLATE.md),[发布一个pull request](https://help.github.com/articles/using-pull-requests/)你的小知识将被审查(见下文)。
# 提示
将时间和小知识number保留为**xx**。当PR为`ready to merge`状态时,我们将告诉你正确的数字。请同时[squash](https://davidwalsh.name/squash-commits-git)你的commits.
# 工作流程
**Tip 提交** ⇒ **Tip 审查** ⇒ **Tip 通过并发布**
- 当你提交 tip 时,如果 tip 正在通过审查,此时 tip 状态为 `under review`。
- 如果 tip 经过5个人的审查,而且他們都给了 :shipit:,tip 将会被合并(`merge`)到 tip 列表中。
期待您的贡献!
================================================
FILE: CONTRIBUTING_zh_TW.md
================================================
# 如何提交你的 tip
如果要提交 tip 到目錄,fork 這個儲存庫(repository)並加入你的 tip 到檔案內,放入到正確的資料夾(根據語系)。檔案名稱應該為 `2016-xx-xx-name-of-your-tip`。
當你撰寫你的 tip 時,請使用[這個格式](POST_TEMPLATE.md)。
### 要求
- tip 應該至少可以在兩分鐘內讀懂。
- 你可以連結到其他的網站或者是影片讓我們了解更多。
- 程式碼區塊使用 ```js。
- 避免在 title 提到「JavaScript」(因為我們的 tips 都是與 JavaScript 相關的)。
- 使用反引號(`)來標記程式碼 - _警告_:tip **標題**和 **tip-tldr** 不要使用反引號。
當你的 tip 準備好了,依據這個 [PR 樣板](PULL_REQUEST_TEMPLATE.md),[發送一個 PR](https://help.github.com/articles/using-pull-requests/) 你的 tip 將會被校閱。每天都會有 tip 從可用的 PR 中被合併(merged)。
## 注意
使用 **xx** 為日期和 tip 的編號。當我們決定合併你的 PR 你可以把它們增加並 [squash](https://davidwalsh.name/squash-commits-git) 到你的 commits。
## Tip 工作流程
**Tip 發送** ⇒ **Tip 審查** ⇒ **Tip 接受並發布**
- 當你提交 tip 時,如果 tip 正在校閱流程,則 tip 狀態為 `under-review`。
- 如果 tip 經過 5 位專業的人士校閱,而且他們都給了 :shipit:,tip 將會被合併(`merge`)到 tip 清單。
================================================
FILE: LICENSE.md
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
================================================
FILE: POST_TEMPLATE.md
================================================
---
layout: *post
title: Demo post
tip-number: xx
tip-username: tip_js
tip-username-profile: https://twitter.com/tips_js
tip-tldr: Just a demo
<!-- tip-writer-support: Paypal, Coinbase, Etc -->
<!-- tip-translator-support: Paypal, Coinbase, Etc -->
categories:
- en
---
content here
### Subtitles format
================================================
FILE: PULL_REQUEST_TEMPLATE.md
================================================
## [Title here]
## TL;DR;
[content here]
## Username
[twitter account link or github account link ej: [@tips-js](https://twitter.com/tips_js)]
## Extra
[content here]
================================================
FILE: README.md
================================================
[](https://www.jstips.co/book/?utm_source=github&utm_medium=header&utm_campaign=book&utm_content=pro)
# JS Tips [](https://github.com/sindresorhus/awesome)
> Useful JavaScript tips
This is an awesome project about short and useful JavaScript tips that will help you improve your code writing. In less than 2 minutes, you can read about performance, conventions, hacks, interview questions and all the items that the future of this awesome language holds for us.
Tips are added frequently (read further if you want to stay in touch).
## Support the community
If you found a JS Tip useful or if you like a writer of the community, you can show your support and respect with a tip!
### Can you help us enrich it?
Sure, you can help the project in two ways: sending a tip or reviewing future tips.
Any improvements or suggestions are more than welcome!
[Instructions are here](https://github.com/loverajoel/jstips/blob/master/CONTRIBUTING.md).
### Let’s keep in touch
There are a lot of ways to get updates:
- [Official Blog](http://www.jstips.co)
- [Official Twitter Account](https://twitter.com/tips_js)
- [Hubot](https://github.com/dggriffin/hubot-jstips)
- [Slackbot](https://github.com/radibit/js-tips-slack-bot)
- [iOS App](https://goo.gl/Y9WiBc)
> Don't forget to Star★ the repo, as this helps promote the project!
# Tips list
- 74 - [Check the reason make your page re-render by changed props and state](http://www.jstips.co/en/react/trace-the-reason-make-your-page-rerender/)
- 73 - [Hash maps without side effects](http://www.jstips.co/en/javascript/hash-maps-without-side-effects/)
- 72 - [Adventurers Guide to React (Part I)](http://www.jstips.co/en/react/adventurers-guide-to-react/)
- 71 - [VueJS, How VueJS makes a copy-update-replace inside the data binding](http://www.jstips.co/en/more/vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding/)
- 70 - [Picking and rejecting object properties](http://www.jstips.co/en/javascript/picking-and-rejecting-object-properties/)
- 69 - [Enhancing React components, Composition](http://www.jstips.co/en/react/enhancing-react-components-composition/)
- 68 - [Why you should use Object.is() in equality comparison](http://www.jstips.co/en/javascript/why-you-should-use-Object.is()-in-equality-comparison/)
- 67 - [Recursion, iteration and tail calls in JS](http://www.jstips.co/en/javascript/recursion-iteration-and-tail-calls-in-js/)
- 66 - [State to Props maps with memory](http://www.jstips.co/en/react/state-to-props-maps-with-memory/)
- 65 - [Tapping for quick debugging](http://www.jstips.co/en/javascript/tapping-for-quick-debugging/)
- 64 - [3 Array Hacks](http://www.jstips.co/en/javascript/3-array-hacks/)
- 63 - [Working With Websocket Timeout](http://www.jstips.co/en/javascript/working-with-websocket-timeout/)
- 62 - [Preventing Unwanted Scopes Creation in AngularJs](http://www.jstips.co/en/angular/preventing-unwanted-scopes-creation-in-angularjs/)
- 61 - [Binding objects to functions](http://www.jstips.co/en/javascript/binding-objects-to-functions/)
- 60 - [Three useful hacks](http://www.jstips.co/en/javascript/three-useful-hacks/)
- 59 - [ES6, var vs let](http://www.jstips.co/en/javascript/keyword-var-vs-let/)
- 58 - [Breaking or continuing loop in functional programming](http://www.jstips.co/en/javascript/break-continue-loop-functional/)
- 57 - [Comma operator in JS](http://www.jstips.co/en/javascript/comma-operaton-in-js/)
- 56 - [Copy to Clipboard](http://www.jstips.co/en/javascript/copy-to-clipboard/)
- 55 - [Create an easy loop using an array](http://www.jstips.co/en/javascript/make-easy-loop-on-array/)
- 54 - [How to use optional arguments in functions (with optional callback)](http://www.jstips.co/en/javascript/use-optional-arguments/)
- 53 - [Get File Extension](http://www.jstips.co/en/javascript/get-file-extension/)
- 52 - [Return Values with the 'new' Operator](http://www.jstips.co/en/javascript/return-values-with-the-new-operator/)
- 51 - [DOM event listening made easy](http://www.jstips.co/en/javascript/DOM-event-listening-made-easy/)
- 50 - [Helpful Console Logging Tricks](http://www.jstips.co/en/javascript/helpful-console-log-hacks/)
- 49 - [Easiest way to extract Unix timestamps](http://www.jstips.co/en/javascript/extract-unix-timestamp-easily/)
- 48 - [Reduce builtin function usage](http://www.jstips.co/en/javascript/reminders-about-reduce-function-usage/)
- 47 - [Basics: Declarations](http://www.jstips.co/en/javascript/basics-declarations/)
- 46 - [Detect document ready in pure JS](http://www.jstips.co/en/javascript/detect-document-ready-in-pure-js/)
- 45 - [Calculate the Max/Min value from an array](http://www.jstips.co/en/javascript/calculate-the-max-min-value-from-an-array/)
- 44 - [Know the passing mechanism](http://www.jstips.co/en/javascript/know-the-passing-mechanism/)
- 43 - [Use destructuring in function parameters](http://www.jstips.co/en/javascript/use-destructuring-in-function-parameters/)
- 42 - [Preventing Unapply Attacks](http://www.jstips.co/en/javascript/preventing-unapply-attacks/)
- 41 - [Array average and median](http://www.jstips.co/en/javascript/array-average-and-median/)
- 40 - [Using JSON.stringify](http://www.jstips.co/en/javascript/using-json-stringify/)
- 39 - [Advanced Properties](http://www.jstips.co/en/javascript/advanced-properties/)
- 38 - [Flattening multidimensional Arrays](http://www.jstips.co/en/javascript/flattening-multidimensional-arrays-in-javascript/)
- 37 - [Deduplicate an Array](http://www.jstips.co/en/javascript/deduplicate-an-array/)
- 36 - [Observe DOM changes in extensions](http://www.jstips.co/en/javascript/observe-dom-changes/)
- 35 - [Assignment Operators](http://www.jstips.co/en/javascript/assignment-shorthands/)
- 34 - [Implementing asynchronous loop](http://www.jstips.co/en/javascript/implementing-asynchronous-loops/)
- 33 - [Create Range 0...N easily using one line](http://www.jstips.co/en/javascript/create-range-0-n-easily-using-one-line/)
- 32 - [`Map()` to the rescue: adding order to Object properties](http://www.jstips.co/en/javascript/map-to-the-rescue-adding-order-to-object-properties/)
- 31 - [Avoid modifying or passing `arguments` into other functions — it kills optimization](http://www.jstips.co/en/javascript/avoid-modifying-or-passing-arguments-into-other-functions-it-kills-optimization/)
- 30 - [Converting truthy/falsy values to boolean](http://www.jstips.co/en/javascript/converting-truthy-falsy-values-to-boolean/)
- 29 - [Speed up recursive functions with memoization](http://www.jstips.co/en/javascript/speed-up-recursive-functions-with-memoization/)
- 28 - [Currying vs partial application](http://www.jstips.co/en/javascript/curry-vs-partial-application/)
- 27 - [Short circuit evaluation](http://www.jstips.co/en/javascript/short-circuit-evaluation-in-js/)
- 26 - [Filtering and sorting a list of Strings](http://www.jstips.co/en/javascript/filtering-and-sorting-a-list-of-strings/)
- 25 - [Using immediately invoked function expression](http://www.jstips.co/en/javascript/Using-immediately-invoked-function-expression/)
- 24 - [Use `===` instead of `==`](http://www.jstips.co/en/javascript/use_===_instead_of_==/)
- 23 - [Converting to number fast way](http://www.jstips.co/en/javascript/converting-to-number-fast-way/)
- 22 - [Empty an Array](http://www.jstips.co/en/javascript/two-ways-to-empty-an-array/)
- 21 - [Shuffle an Array](http://www.jstips.co/en/javascript/shuffle-an-array/)
- 20 - [Return objects to enable chaining of functions](http://www.jstips.co/en/javascript/return-objects-to-enable-chaining-of-functions/)
- 19 - [Safe String concatenation](http://www.jstips.co/en/javascript/safe-string-concatenation/)
- 18 - [Truncating the fast (but risky) way](http://www.jstips.co/en/javascript/rounding-the-fast-way/)
- 17 - [Node.js: Run a module if it is not "required"](http://www.jstips.co/en/javascript/nodejs-run-a-module-if-it-is-not-required/)
- 16 - [Passing arguments to callback functions](http://www.jstips.co/en/javascript/passing-arguments-to-callback-functions/)
- 15 - [Even simpler way of using `indexOf` as a contains clause](http://www.jstips.co/en/javascript/even-simpler-way-of-using-indexof-as-a-contains-clause/)
- 14 - [Fat Arrow Functions #ES6](http://www.jstips.co/en/javascript/fat-arrow-functions/)
- 13 - [Measure performance of a code block](http://www.jstips.co/en/javascript/tip-to-measure-performance-of-a-javascript-block/)
- 12 - [Pseudomandatory parameters in ES6 functions #ES6](http://www.jstips.co/en/javascript/pseudomandatory-parameters-in-es6-functions/)
- 11 - [Hoisting](http://www.jstips.co/en/javascript/hoisting/)
- 10 - [Check if a property is in an Object](http://www.jstips.co/en/javascript/check-if-a-property-is-in-a-object/)
- 09 - [Template Strings](http://www.jstips.co/en/javascript/template-strings/)
- 08 - [Converting a Node List to an Array](http://www.jstips.co/en/javascript/converting-a-node-list-to-an-array/)
- 07 - ["use strict" and get lazy](http://www.jstips.co/en/javascript/use-strict-and-get-lazy/)
- 06 - [Writing a single method for arrays and a single element](http://www.jstips.co/en/javascript/writing-a-single-method-for-arrays-and-a-single-element/)
- 05 - [Differences between `undefined` and `null`](http://www.jstips.co/en/javascript/differences-between-undefined-and-null/)
- 04 - [Sorting Strings with accented characters](http://www.jstips.co/en/javascript/sorting-strings-with-accented-characters/)
- 03 - [Improve Nested Conditionals](http://www.jstips.co/en/javascript/improve-nested-conditionals/)
- 02 - [ReactJS - Keys in children components are important](http://www.jstips.co/en/react/keys-in-children-components-are-important/)
- 01 - [AngularJS: `$digest` vs `$apply`](http://www.jstips.co/en/angular/angularjs-digest-vs-apply/)
- 00 - [Insert item inside an Array](http://www.jstips.co/en/javascript/insert-item-inside-an-array/)
### License
[GNU GENERAL PUBLIC LICENSE](https://github.com/loverajoel/jstips/blob/master/LICENSE.md)
================================================
FILE: _posts/en/angular/2016-01-01-angularjs-digest-vs-apply.md
================================================
---
layout: post
title: AngularJs - `$digest` vs `$apply`
tip-number: 01
tip-username: loverajoel
tip-username-profile: https://github.com/loverajoel
tip-tldr: JavaScript modules and build steps are getting more numerous and complicated, but what about boilerplate in new frameworks?
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/angularjs-digest-vs-apply/
categories:
- en
- angular
---
One of the most appreciated features of AngularJs is the two-way data binding. In order to make this work AngularJs evaluates the changes between the model and the view through cycles(`$digest`). You need to understand this concept in order to understand how the framework works under the hood.
Angular evaluates each watcher whenever one event is fired. This is the known `$digest` cycle.
Sometimes you have to force it to run a new cycle manually and you must choose the correct option because this phase is one of the most influential in terms of performance.
### `$apply`
This core method lets you to start the digestion cycle explicitly. That means that all watchers are checked; the entire application starts the `$digest loop`. Internally, after executing an optional function parameter, it calls `$rootScope.$digest();`.
### `$digest`
In this case the `$digest` method starts the `$digest` cycle for the current scope and its children. You should notice that the parent's scopes will not be checked.
and not be affected.
### Recommendations
- Use `$apply` or `$digest` only when browser DOM events have triggered outside of AngularJS.
- Pass a function expression to `$apply`, this has an error handling mechanism and allows integrating changes in the digest cycle.
```javascript
$scope.$apply(() => {
$scope.tip = 'Javascript Tip';
});
```
- If you only need to update the current scope or its children, use `$digest`, and prevent a new digest cycle for the whole application. The performance benefit is self-evident.
- `$apply()` is a hard process for the machine and can lead to performance issues when there is a lot of binding.
- If you are using >AngularJS 1.2.X, use `$evalAsync`, which is a core method that will evaluate the expression during the current cycle or the next. This can improve your application's performance
================================================
FILE: _posts/en/angular/2017-03-07-preventing-unwanted-scopes-creation-in-angularjs.md
================================================
---
layout: post
title: Preventing Unwanted Scopes Creation in AngularJs
tip-number: 62
tip-username: loverajoel
tip-username-profile: https://github.com/loverajoel
tip-tldr: In this tip I am going to show how to pass data between scopes preventing unwanted scopes created by `ng-repeat` and `ng-if`
tip-writer-support: https://www.coinbase.com/loverajoel
categories:
- en
- angular
---
One of the most appreciated features of AngularJs is thUnderstanding and preventing ```ng-model``` data scope is one of the main challenge you get quite often.
While working with ```ng-model``` data, new unwanted scope can be created by ```ng-repeat``` or ```ng-if``` procedures.
Take a look on following example-
```js
<div ng-app>
<input type="text" ng-model="data">
<div ng-repeat="i in [1]">
<input type="text" ng-model="data"><br/>
innerScope:{{data}}
</div>
outerScope:{{data}}
</div>
```
In the above example, ```innerScope``` inherits from ```outerScope``` and pass the value in ```outerScope```.
If you input a value in ```innerScope``` it will reflect in ```outerScope```. But if you edit ```outerScope```,
```innerScope``` doesn’t reflect the same value as ```outerScope``` because ```innerScope``` creates its own field
so no longer inherits from ```outerScope```.
To prevent this to happen we can use “Controller As” approach instead of using scope as a container
for all data and functions. But one more catchy solution is to keep everything in objects as shown is below example-
```js
<div ng-app>
<input type="text" ng-model="data.text">
<div ng-repeat="i in [1]">
<input type="text" ng-model="data.text"><br/>
inner scope:{{data.text}}
</div>
outer scope:{{data.text}}
</div>
```
Now ```innerScope``` is no longer creates a new field and editing value in either ```innerScope``` or ```outerScope``` will
reflect in both ```innerScope``` and ```outerScope```.
================================================
FILE: _posts/en/javascript/2015-12-29-insert-item-inside-an-array.md
================================================
---
layout: post
title: Insert item inside an Array
tip-number: 00
tip-username: loverajoel
tip-username-profile: https://github.com/loverajoel
tip-tldr: Inserting an item into an existing array is a daily common task. You can add elements to the end of an array using push, to the beginning using unshift, or to the middle using splice.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/insert-item-inside-an-array/
categories:
- en
- javascript
---
# Inserting an item into an existing array
Inserting an item into an existing array is a daily common task. You can add elements to the end of an array using push, to the beginning using unshift, or to the middle using splice.
Those are known methods, but it doesn't mean there isn't a more performant way. Here we go:
## Adding an element at the end
Adding an element at the end of the array is easy with push(), but it can be done in different ways.
```javascript
var arr = [1,2,3,4,5];
var arr2 = [];
arr.push(6);
arr[arr.length] = 6;
arr2 = arr.concat([6]);
```
Both first methods modify the original array. Don't believe me? Check the [jsperf](http://jsperf.com/push-item-inside-an-array)
### Performance on mobile :
#### Android (v4.2.2)
1. _arr.push(6);_ and _arr[arr.length] = 6;_ have the same performance // 3 319 694 ops/sec
3. _arr2 = arr.concat([6]);_ 50.61 % slower than the other two methods
#### Chrome Mobile (v33.0.0)
1. _arr[arr.length] = 6;_ // 6 125 975 ops/sec
2. _arr.push(6);_ 66.74 % slower
3. _arr2 = arr.concat([6]);_ 87.63 % slower
#### Safari Mobile (v9)
1. _arr[arr.length] = 6;_ // 7 452 898 ops/sec
2. _arr.push(6);_ 40.19 % slower
3. _arr2 = arr.concat([6]);_ 49.78 % slower
```javascript
Final victor
1. arr[arr.length] = 6; // with an average of 5 632 856 ops/sec
2. arr.push(6); // 35.64 % slower
3. arr2 = arr.concat([6]); // 62.67 % slower
```
### Performance on desktop
#### Chrome (v48.0.2564)
1. _arr[arr.length] = 6;_ // 21 602 722 ops/sec
2. _arr.push(6);_ 61.94 % slower
3. _arr2 = arr.concat([6]);_ 87.45 % slower
#### Firefox (v44)
1. _arr.push(6);_ // 56 032 805 ops/sec
2. _arr[arr.length] = 6;_ 0.52 % slower
3. _arr2 = arr.concat([6]);_ 87.36 % slower
#### IE (v11)
1. _arr[arr.length] = 6;_ // 67 197 046 ops/sec
2. _arr.push(6);_ 39.61 % slower
3. _arr2 = arr.concat([6]);_ 93.41 % slower
#### Opera (v35.0.2066.68)
1. _arr[arr.length] = 6;_ // 30 775 071 ops/sec
2. _arr.push(6);_ 71.60 % slower
3. _arr2 = arr.concat([6]);_ 83.70 % slower
#### Safari (v9.0.3)
1. _arr.push(6);_ // 42 670 978 ops/sec
2. _arr[arr.length] = 6;_ 0.80 % slower
3. _arr2 = arr.concat([6]);_ 76.07 % slower
```javascript
Final victor
1. arr[arr.length] = 6; // with an average of 42 345 449 ops/sec
2. arr.push(6); // 34.66 % slower
3. arr2 = arr.concat([6]); // 85.79 % slower
```
## Add an element at the beginning
Now if we are trying to add an item to the beginning of the array:
```javascript
var arr = [1,2,3,4,5];
arr.unshift(0);
[0].concat(arr);
```
Here is a little more detail: unshift edits the original array; concat returns a new array. [jsperf](http://jsperf.com/unshift-item-inside-an-array)
### Performance on mobile :
#### Android (v4.2.2)
1. _[0].concat(arr);_ // 1 808 717 ops/sec
2. _arr.unshift(0);_ 97.85 % slower
#### Chrome Mobile (v33.0.0)
1. _[0].concat(arr);_ // 1 269 498 ops/sec
2. _arr.unshift(0);_ 99.86 % slower
#### Safari Mobile (v9)
1. _arr.unshift(0);_ // 3 250 184 ops/sec
2. _[0].concat(arr);_ 33.67 % slower
```javascript
Final victor
1. [0].concat(arr); // with an average of 4 972 622 ops/sec
2. arr.unshift(0); // 64.70 % slower
```
### Performance on desktop
#### Chrome (v48.0.2564)
1. _[0].concat(arr);_ // 2 656 685 ops/sec
2. _arr.unshift(0);_ 96.77 % slower
#### Firefox (v44)
1. _[0].concat(arr);_ // 8 039 759 ops/sec
2. _arr.unshift(0);_ 99.72 % slower
#### IE (v11)
1. _[0].concat(arr);_ // 3 604 226 ops/sec
2. _arr.unshift(0);_ 98.31 % slower
#### Opera (v35.0.2066.68)
1. _[0].concat(arr);_ // 4 102 128 ops/sec
2. _arr.unshift(0);_ 97.44 % slower
#### Safari (v9.0.3)
1. _arr.unshift(0);_ // 12 356 477 ops/sec
2. _[0].concat(arr);_ 15.17 % slower
```javascript
Final victor
1. [0].concat(arr); // with an average of 6 032 573 ops/sec
2. arr.unshift(0); // 78.65 % slower
```
## Add an element in the middle
Adding items in the middle of an array is easy with splice, and it's the most performant way to do it.
```javascript
var items = ['one', 'two', 'three', 'four'];
items.splice(items.length / 2, 0, 'hello');
```
I tried to run these tests in various Browsers and OS and the results were similar. I hope these tips will be useful for you and encourage to perform your own tests!
================================================
FILE: _posts/en/javascript/2016-01-03-improve-nested-conditionals.md
================================================
---
layout: post
title: Improve Nested Conditionals
tip-number: 03
tip-username: AlbertoFuente
tip-username-profile: https://github.com/AlbertoFuente
tip-tldr: How can we improve and make a more efficient nested `if` statement in javascript?
redirect_from:
- /en/improve-nested-conditionals/
categories:
- en
- javascript
---
How can we improve and make a more efficient nested `if` statement in javascript?
```javascript
if (color) {
if (color === 'black') {
printBlackBackground();
} else if (color === 'red') {
printRedBackground();
} else if (color === 'blue') {
printBlueBackground();
} else if (color === 'green') {
printGreenBackground();
} else {
printYellowBackground();
}
}
```
One way to improve the nested `if` statement would be using the `switch` statement. Although it is less verbose and is more ordered, it's not recommended to use it because it's so difficult to debug errors. Here's [why](https://toddmotto.com/deprecating-the-switch-statement-for-object-literals).
```javascript
switch(color) {
case 'black':
printBlackBackground();
break;
case 'red':
printRedBackground();
break;
case 'blue':
printBlueBackground();
break;
case 'green':
printGreenBackground();
break;
default:
printYellowBackground();
}
```
But what if we have a conditional with several checks in each statement? In this case, if we want it less verbose and more ordered, we can use the conditional `switch`.
If we pass `true` as a parameter to the `switch` statement, it allows us to put a conditional in each case.
```javascript
switch(true) {
case (typeof color === 'string' && color === 'black'):
printBlackBackground();
break;
case (typeof color === 'string' && color === 'red'):
printRedBackground();
break;
case (typeof color === 'string' && color === 'blue'):
printBlueBackground();
break;
case (typeof color === 'string' && color === 'green'):
printGreenBackground();
break;
case (typeof color === 'string' && color === 'yellow'):
printYellowBackground();
break;
}
```
If refactoring is an option, we can try to simplify the functions themselves. For example instead of having a function for each background color we could have an function that takes the color as an argument.
```javascript
function printBackground(color) {
if (!color || typeof color !== 'string') {
return; // Invalid color, return immediately
}
}
```
But if refactoring is not an option, we must always avoid having several checks in every condition and avoid using `switch` as much as possible. We also must take into account that the most efficient way to do this is through an `object`.
```javascript
var colorObj = {
'black': printBlackBackground,
'red': printRedBackground,
'blue': printBlueBackground,
'green': printGreenBackground,
'yellow': printYellowBackground
};
if (color in colorObj) {
colorObj[color]();
}
```
Here you can find more information about [this](http://www.nicoespeon.com/en/2015/01/oop-revisited-switch-in-js/).
================================================
FILE: _posts/en/javascript/2016-01-04-sorting-strings-with-accented-characters.md
================================================
---
layout: post
title: Sorting strings with accented characters
tip-number: 04
tip-username: loverajoel
tip-username-profile: https://github.com/loverajoel
tip-tldr: Javascript has a native method **sort** that allows sorting arrays. Doing a simple `array.sort()` will treat each array entry as a string and sort it alphabetically. But when you try order an array of non ASCII characters you will obtain a strange result.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/sorting-strings-with-accented-characters/
categories:
- en
- javascript
---
Javascript has a native method **[sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)** that allows sorting arrays. Doing a simple `array.sort()` will treat each array entry as a string and sort it alphabetically. Also you can provide your [own custom sorting](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters) function.
```javascript
['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort();
// ["Buenos Aires", "Mumbai", "New York", "Shanghai"]
```
But when you try order an array of non ASCII characters like this `['é', 'a', 'ú', 'c']`, you will obtain a strange result `['c', 'e', 'á', 'ú']`. That happens because sort works only with the English language.
See the next example:
```javascript
// Spanish
['único','árbol', 'cosas', 'fútbol'].sort();
// ["cosas", "fútbol", "árbol", "único"] // bad order
// German
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort();
// ["Wann", "Woche", "wäre", "wöchentlich"] // bad order
```
Fortunately, there are two ways to overcome this behavior [localeCompare](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) and [Intl.Collator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator) provided by ECMAScript Internationalization API.
> Both methods have their own custom parameters in order to configure it to work adequately.
### Using `localeCompare()`
```javascript
['único','árbol', 'cosas', 'fútbol'].sort(function (a, b) {
return a.localeCompare(b);
});
// ["árbol", "cosas", "fútbol", "único"]
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(function (a, b) {
return a.localeCompare(b);
});
// ["Wann", "wäre", "Woche", "wöchentlich"]
```
### Using `Intl.Collator()`
```javascript
['único','árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare);
// ["árbol", "cosas", "fútbol", "único"]
['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare);
// ["Wann", "wäre", "Woche", "wöchentlich"]
```
- For each method you can customize the location.
- According to [Firefox](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Performance) Intl.Collator is faster when comparing large numbers of strings.
So when you are working with arrays of strings in a language other than English, remember to use this method to avoid unexpected sorting.
================================================
FILE: _posts/en/javascript/2016-01-05-differences-between-undefined-and-null.md
================================================
---
layout: post
title: Differences between `undefined` and `null`
tip-number: 05
tip-username: loverajoel
tip-username-profile: https://github.com/loverajoel
tip-tldr: Understanding the differences between `undefined` and `null`.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/differences-between-undefined-and-null/
categories:
- en
- javascript
---
- `undefined` means a variable has not been declared, or has been declared but has not yet been assigned a value
- `null` is an assignment value that means "no value"
- Javascript sets unassigned variables with a default value of `undefined`
- Javascript never sets a value to `null`. It is used by programmers to indicate that a `var` has no value.
- `undefined` is not valid in JSON while `null` is
- `undefined` typeof is `undefined`
- `null` typeof is an `object`. [Why?](http://www.2ality.com/2013/10/typeof-null.html)
- Both are primitives
- Both are [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)
(`Boolean(undefined) // false`, `Boolean(null) // false`)
- You can know if a variable is [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)
```javascript
typeof variable === "undefined"
```
- You can check if a variable is [null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null)
```javascript
variable === null
```
- The **equality** operator considers them equal, but the **identity** doesn't
```javascript
null == undefined // true
null === undefined // false
```
================================================
FILE: _posts/en/javascript/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
================================================
---
layout: post
title: Writing a single method for arrays and a single element
tip-number: 06
tip-username: mattfxyz
tip-username-profile: https://twitter.com/mattfxyz
tip-tldr: Rather than writing separate methods to handle an array and a single element parameter, write your functions so they can handle both. This is similar to how some of jQuery's functions work (`css` will modify everything matched by the selector).
redirect_from:
- /en/writing-a-single-method-for-arrays-and-a-single-element/
categories:
- en
- javascript
---
Rather than writing separate methods to handle an array and a single element parameter, write your functions so they can handle both. This is similar to how some of jQuery's functions work (`css` will modify everything matched by the selector).
You just have to concat everything into an array first. `Array.concat` will accept an array or a single element.
```javascript
function printUpperCase(words) {
var elements = [].concat(words || []);
for (var i = 0; i < elements.length; i++) {
console.log(elements[i].toUpperCase());
}
}
```
`printUpperCase` is now ready to accept a single node or an array of nodes as its parameter. It also avoids the potential `TypeError` that would be thrown if no parameter was passed.
```javascript
printUpperCase("cactus");
// => CACTUS
printUpperCase(["cactus", "bear", "potato"]);
// => CACTUS
// BEAR
// POTATO
```
================================================
FILE: _posts/en/javascript/2016-01-07-use-strict-and-get-lazy.md
================================================
---
layout: post
title: use strict and get lazy
tip-number: 07
tip-username: nainslie
tip-username-profile: https://twitter.com/nat5an
tip-tldr: Strict-mode JavaScript makes it easier for the developer to write "secure" JavaScript.
redirect_from:
- /en/use-strict-and-get-lazy/
categories:
- en
- javascript
---
Strict-mode JavaScript makes it easier for the developer to write "secure" JavaScript.
By default, JavaScript allows the programmer to be pretty careless, for example, by not requiring us to declare our variables with "var" when we first introduce them. While this may seem like a convenience to the unseasoned developer, it's also the source of many errors when a variable name is misspelled or accidentally referred to out of its scope.
Programmers like to make the computer do the boring stuff for us, and automatically check our work for mistakes. That's what the JavaScript "use strict" directive allows us to do, by turning our mistakes into JavaScript errors.
We add this directive either by adding it at the top of a js file:
```javascript
// Whole-script strict mode syntax
"use strict";
var v = "Hi! I'm a strict mode script!";
```
or inside a function:
```javascript
function f()
{
// Function-level strict mode syntax
'use strict';
function nested() { return "And so am I!"; }
return "Hi! I'm a strict mode function! " + nested();
}
function f2() { return "I'm not strict."; }
```
By including this directive in a JavaScript file or function, we will direct the JavaScript engine to execute in strict mode which disables a bunch of behaviors that are usually undesirable in larger JavaScript projects. Among other things, strict mode changes the following behaviors:
* Variables can only be introduced when they are preceded with "var"
* Attempting to write to read-only properties generates a noisy error
* You have to call constructors with the "new" keyword
* "this" is not implicitly bound to the global object
* Very limited use of eval() allowed
* Protects you from using reserved words or future reserved words as variable names
Strict mode is great for new projects, but can be challenging to introduce into older projects that don't already use it in most places. It also can be problematic if your build chain concatenates all your js files into one big file, as this may cause all files to execute in strict mode.
It is not a statement, but a literal expression, ignored by earlier versions of JavaScript.
Strict mode is supported in:
* Internet Explorer from version 10.
* Firefox from version 4.
* Chrome from version 13.
* Safari from version 5.1.
* Opera from version 12.
[See MDN for a fuller description of strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode).
================================================
FILE: _posts/en/javascript/2016-01-08-converting-a-node-list-to-an-array.md
================================================
---
layout: post
title: Converting a Node List to an Array
tip-number: 08
tip-username: Tevko
tip-username-profile: https://twitter.com/tevko
tip-tldr: Here's a quick, safe, and reusable way to convert a node list into an array of DOM elements.
redirect_from:
- /en/converting-a-node-list-to-an-array/
categories:
- en
- javascript
---
The `querySelectorAll` method returns an array-like object called a node list. These data structures are referred to as "Array-like", because they appear as an array, but can not be used with array methods like `map` and `forEach`. Here's a quick, safe, and reusable way to convert a node list into an array of DOM elements:
```javascript
const nodelist = document.querySelectorAll('div');
const nodelistToArray = Array.apply(null, nodelist);
//later on ..
nodelistToArray.forEach(...);
nodelistToArray.map(...);
nodelistToArray.slice(...);
//etc...
```
The `apply` method is used to pass an array of arguments to a function with a given `this` value. [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) states that `apply` will take an array-like object, which is exactly what `querySelectorAll` returns. Since we don't need to specify a value for `this` in the context of the function, we pass in `null` or `0`. The result is an actual array of DOM elements which contains all of the available array methods.
Alternatively you can use `Array.prototype.slice` combined with `Function.prototype.call` or `Function.prototype.apply` passing the array-like object as the value of `this`:
```javascript
const nodelist = document.querySelectorAll('div');
const nodelistToArray = Array.prototype.slice.call(nodelist); // or equivalently Array.prototype.slice.apply(nodelist);
//later on ..
nodelistToArray.forEach(...);
nodelistToArray.map(...);
nodelistToArray.slice(...);
//etc...
```
Or if you are using ES2015 you can use the [spread operator `...`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)
```js
const nodelist = [...document.querySelectorAll('div')]; // returns a real array
//later on ..
nodelist.forEach(...);
nodelist.map(...);
nodelist.slice(...);
//etc...
```
================================================
FILE: _posts/en/javascript/2016-01-09-template-strings.md
================================================
---
layout: post
title: Template Strings
tip-number: 09
tip-username: JakeRawr
tip-username-profile: https://github.com/JakeRawr
tip-tldr: As of ES6, JS now has template strings as an alternative to the classic end quotes strings.
redirect_from:
- /en/template-strings/
categories:
- en
- javascript
---
As of ES6, JS now has template strings as an alternative to the classic end quotes strings.
Ex:
Normal string
```javascript
var firstName = 'Jake';
var lastName = 'Rawr';
console.log('My name is ' + firstName + ' ' + lastName);
// My name is Jake Rawr
```
Template String
```javascript
var firstName = 'Jake';
var lastName = 'Rawr';
console.log(`My name is ${firstName} ${lastName}`);
// My name is Jake Rawr
```
You can do multi-line strings without `\n`, perform simple logic (ie 2+3) or even use the [ternary operator](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) inside `${}` in template strings.
```javascript
var val1 = 1, val2 = 2;
console.log(`${val1} is ${val1 < val2 ? 'less than': 'greater than'} ${val2}`)
// 1 is less than 2
```
You are also able to modify the output of template strings using a function; they are called [tagged template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings#Tagged_template_strings) for example usages of tagged template strings.
You may also want to [read](https://hacks.mozilla.org/2015/05/es6-in-depth-template-strings-2) to understand template strings more.
================================================
FILE: _posts/en/javascript/2016-01-10-check-if-a-property-is-in-a-object.md
================================================
---
layout: post
title: Check if a property is in a Object
tip-number: 10
tip-username: loverajoel
tip-username-profile: https://www.twitter.com/loverajoel
tip-tldr: These are ways to check if a property is present in an object.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/check-if-a-property-is-in-a-object/
categories:
- en
- javascript
---
When you have to check if a property is present in an [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects), you probably are doing something like this:
```javascript
var myObject = {
name: '@tips_js'
};
if (myObject.name) { ... }
```
That's ok, but you have to know that there are two native ways for this kind of thing, the [`in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in) and [`Object.hasOwnProperty`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty). Every object descended from `Object`, has both ways available.
### See the big Difference
```javascript
var myObject = {
name: '@tips_js'
};
myObject.hasOwnProperty('name'); // true
'name' in myObject; // true
myObject.hasOwnProperty('valueOf'); // false, valueOf is inherited from the prototype chain
'valueOf' in myObject; // true
```
Both differ in the depth at which they check the properties. In other words, `hasOwnProperty` will only return true if key is available on that object directly. However, the `in` operator doesn't discriminate between properties created on an object and properties inherited from the prototype chain.
Here's another example:
```javascript
var myFunc = function() {
this.name = '@tips_js';
};
myFunc.prototype.age = '10 days';
var user = new myFunc();
user.hasOwnProperty('name'); // true
user.hasOwnProperty('age'); // false, because age is from the prototype chain
```
Check the [live examples here](https://jsbin.com/tecoqa/edit?js,console)!
I also recommend reading [this discussion](https://github.com/loverajoel/jstips/issues/62) about common mistakes made when checking a property's existence in objects.
================================================
FILE: _posts/en/javascript/2016-01-11-hoisting.md
================================================
---
layout: post
title: Hoisting
tip-number: 11
tip-username: squizzleflip
tip-username-profile: https://twitter.com/squizzleflip
tip-tldr: Understanding hoisting will help you organize your function scope.
redirect_from:
- /en/hoisting/
categories:
- en
- javascript
---
Understanding [hoisting](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting) will help you organize your function scope. Just remember, variable declarations and function definitions are hoisted to the top. Variable definitions are not, even if you declare and define a variable on the same line. Also, a variable **declaration** lets the system know that the variable exists while **definition** assigns it a value.
```javascript
function doTheThing() {
// ReferenceError: notDeclared is not defined
console.log(notDeclared);
// Outputs: undefined
console.log(definedLater);
var definedLater;
definedLater = 'I am defined!'
// Outputs: 'I am defined!'
console.log(definedLater)
// Outputs: undefined
console.log(definedSimulateneously);
var definedSimulateneously = 'I am defined!'
// Outputs: 'I am defined!'
console.log(definedSimulateneously)
// Outputs: 'I did it!'
doSomethingElse();
function doSomethingElse(){
console.log('I did it!');
}
// TypeError: undefined is not a function
functionVar();
var functionVar = function(){
console.log('I did it!');
}
}
```
To make things easier to read, declare all of your variables at the top of your function scope so it is clear which scope the variables are coming from. Define your variables before you need to use them. Define your functions at the bottom of your scope to keep them out of your way.
================================================
FILE: _posts/en/javascript/2016-01-12-pseudomandatory-parameters-in-es6-functions.md
================================================
---
layout: post
title: Pseudomandatory parameters in ES6 functions
tip-number: 12
tip-username: Avraam Mavridis
tip-username-profile: https://github.com/AvraamMavridis
tip-tldr: In many programming languages the parameters of a function are by default mandatory and the developer has to explicitly define that a parameter is optional.
redirect_from:
- /en/pseudomandatory-parameters-in-es6-functions/
categories:
- en
- javascript
---
In many programming languages the parameters of a function are by default mandatory and the developer has to explicitly define that a parameter is optional. In Javascript, every parameter is optional, but we can enforce this behavior without messing with the actual body of a function, taking advantage of [**es6's default values for parameters**] (http://exploringjs.com/es6/ch_parameter-handling.html#sec_parameter-default-values) feature.
```javascript
const _err = function( message ){
throw new Error( message );
}
const getSum = (a = _err('a is not defined'), b = _err('b is not defined')) => a + b
getSum( 10 ) // throws Error, b is not defined
getSum( undefined, 10 ) // throws Error, a is not defined
```
`_err` is a function that immediately throws an Error. If no value is passed for one of the parameters, the default value is going to be used, `_err` will be called and an Error will be thrown. You can see more examples for the **default parameters feature** on [Mozilla's Developer Network ](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/default_parameters)
================================================
FILE: _posts/en/javascript/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
================================================
---
layout: post
title: Tip to measure performance of a javascript block
tip-number: 13
tip-username: manmadareddy
tip-username-profile: https://twitter.com/manmadareddy
tip-tldr: For quickly measuring performance of a javascript block, we can use the console functions like `console.time(label)` and `console.timeEnd(label)`
redirect_from:
- /en/tip-to-measure-performance-of-a-javascript-block/
categories:
- en
- javascript
---
For quickly measuring performance of a javascript block, we can use the console functions like
[`console.time(label)`](https://developer.chrome.com/devtools/docs/console-api#consoletimelabel) and [`console.timeEnd(label)`](https://developer.chrome.com/devtools/docs/console-api#consoletimeendlabel)
```javascript
console.time("Array initialize");
var arr = new Array(100),
len = arr.length,
i;
for (i = 0; i < len; i++) {
arr[i] = new Object();
};
console.timeEnd("Array initialize"); // Outputs: Array initialize: 0.711ms
```
More info:
[Console object](https://github.com/DeveloperToolsWG/console-object),
[Javascript benchmarking](https://mathiasbynens.be/notes/javascript-benchmarking)
Demo: [jsfiddle](https://jsfiddle.net/meottb62/) - [codepen](http://codepen.io/anon/pen/JGJPoa) (outputs in browser console)
> Note: As [Mozilla](https://developer.mozilla.org/en-US/docs/Web/API/Console/time) suggested don't use this for production sites, use it for development purposes only.
================================================
FILE: _posts/en/javascript/2016-01-14-fat-arrow-functions.md
================================================
---
layout: post
title: Fat Arrow Functions
tip-number: 14
tip-username: pklinger
tip-username-profile: https://github.com/pklinger/
tip-tldr: Introduced as a new feature in ES6, fat arrow functions may come as a handy tool to write more code in fewer lines
redirect_from:
- /en/fat-arrow-functions/
categories:
- en
- javascript
---
Introduced as a new feature in ES6, fat arrow functions may come as a handy tool to write more code in fewer lines. The name comes from its syntax, `=>`, which is a 'fat arrow', as compared to a thin arrow `->`. Some programmers might already know this type of function from different languages such as Haskell, as 'lambda expressions', or as 'anonymous functions'. It is called anonymous, as these arrow functions do not have a descriptive function name.
### What are the benefits?
* Syntax: fewer LOC; no more typing `function` keyword over and over again
* Semantics: capturing the keyword `this` from the surrounding context
### Simple syntax example
Have a look at these two code snippets, which do the exact same job, and you will quickly understand what fat arrow functions do:
```javascript
// general syntax for fat arrow functions
param => expression
// may also be written with parentheses
// parentheses are required on multiple params
(param1 [, param2]) => expression
// using functions
var arr = [5,3,2,9,1];
var arrFunc = arr.map(function(x) {
return x * x;
});
console.log(arr)
// using fat arrow
var arr = [5,3,2,9,1];
var arrFunc = arr.map((x) => x*x);
console.log(arr)
```
As you can see, the fat arrow function in this case can save you time typing out the parentheses as well as the function and return keywords. I would advise you to always write parentheses around the parameter inputs, as the parentheses will be needed for multiple input parameters, such as in `(x,y) => x+y`. It is just a way to cope with forgetting them in different use cases. But the code above would also work like this: `x => x*x`. So far, these are only syntactical improvements, which lead to fewer LOC and better readability.
### Lexically binding `this`
There is another good reason to use fat arrow functions. There is the issue with the context of `this`. With arrow functions, you don't need to worry about `.bind(this)` or setting `that = this` anymore, as fat arrow functions pick the context of `this` from the lexical surrounding. Have a look at the next [example] (https://jsfiddle.net/pklinger/rw94oc11/):
```javascript
// globally defined this.i
this.i = 100;
var counterA = new CounterA();
var counterB = new CounterB();
var counterC = new CounterC();
var counterD = new CounterD();
// bad example
function CounterA() {
// CounterA's `this` instance (!! gets ignored here)
this.i = 0;
setInterval(function () {
// `this` refers to global object, not to CounterA's `this`
// therefore starts counting with 100, not with 0 (local this.i)
this.i++;
document.getElementById("counterA").innerHTML = this.i;
}, 500);
}
// manually binding that = this
function CounterB() {
this.i = 0;
var that = this;
setInterval(function() {
that.i++;
document.getElementById("counterB").innerHTML = that.i;
}, 500);
}
// using .bind(this)
function CounterC() {
this.i = 0;
setInterval(function() {
this.i++;
document.getElementById("counterC").innerHTML = this.i;
}.bind(this), 500);
}
// fat arrow function
function CounterD() {
this.i = 0;
setInterval(() => {
this.i++;
document.getElementById("counterD").innerHTML = this.i;
}, 500);
}
```
Further information about fat arrow functions may be found at [MDN] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). To see different syntax options visit [this site] (http://jsrocks.org/2014/10/arrow-functions-and-their-scope/).
================================================
FILE: _posts/en/javascript/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
================================================
---
layout: post
title: Even simpler way of using `indexOf` as a contains clause
tip-number: 15
tip-username: jhogoforbroke
tip-username-profile: https://twitter.com/jhogoforbroke
tip-tldr: JavaScript by default does not have a contains method. And for checking existence of a substring in a string or an item in an array you may do this.
redirect_from:
- /en/even-simpler-way-of-using-indexof-as-a-contains-clause/
categories:
- en
- javascript
---
JavaScript by default does not have a contains method. And for checking existence of a substring in a string or an item in an array you may do this:
```javascript
var someText = 'javascript rules';
if (someText.indexOf('javascript') !== -1) {
}
// or
if (someText.indexOf('javascript') >= 0) {
}
```
But let's look at these [Expressjs](https://github.com/strongloop/express) code snippets.
[examples/mvc/lib/boot.js](https://github.com/strongloop/express/blob/2f8ac6726fa20ab5b4a05c112c886752868ac8ce/examples/mvc/lib/boot.js#L26)
```javascript
for (var key in obj) {
// "reserved" exports
if (~['name', 'prefix', 'engine', 'before'].indexOf(key)) continue;
```
[lib/utils.js](https://github.com/strongloop/express/blob/2f8ac6726fa20ab5b4a05c112c886752868ac8ce/lib/utils.js#L93)
```javascript
exports.normalizeType = function(type){
return ~type.indexOf('/')
? acceptParams(type)
: { value: mime.lookup(type), params: {} };
};
```
[examples/web-service/index.js](https://github.com/strongloop/express/blob/2f8ac6726fa20ab5b4a05c112c886752868ac8ce/examples/web-service/index.js#L35)
```javascript
// key is invalid
if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));
```
The gotcha is the [bitwise operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) **~**, "Bitwise operators perform their operations on binary representations, but they return standard JavaScript numerical values."
It transforms `-1` into `0`, and `0` evaluates to `false` in JavaScript:
```javascript
var someText = 'text';
!!~someText.indexOf('tex'); // someText contains "tex" - true
!~someText.indexOf('tex'); // someText NOT contains "tex" - false
~someText.indexOf('asd'); // someText doesn't contain "asd" - false
~someText.indexOf('ext'); // someText contains "ext" - true
```
### String.prototype.includes()
ES6 introduced the [includes() method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes) and you can use it to determine whether or not a string includes another string:
```javascript
'something'.includes('thing'); // true
```
With ECMAScript 2016 (ES7) it is even possible to use these techniques with Arrays:
```javascript
!!~[1, 2, 3].indexOf(1); // true
[1, 2, 3].includes(1); // true
```
**Unfortunately, it is only supported in Chrome, Firefox, Safari 9 or above and Edge; not IE11 or lower.**
**It's better used in controlled environments.**
================================================
FILE: _posts/en/javascript/2016-01-16-passing-arguments-to-callback-functions.md
================================================
---
layout: post
title: Passing arguments to callback functions
tip-number: 16
tip-username: minhazav
tip-username-profile: https://twitter.com/minhazav
tip-tldr: By default you cannot pass arguments to a callback function, but you can take advantage of the closure scope in Javascript to pass arguments to callback functions.
redirect_from:
- /en/passing-arguments-to-callback-functions/
categories:
- en
- javascript
---
By default you cannot pass arguments to a callback function. For example:
```js
function callback() {
console.log('Hi human');
}
document.getElementById('someelem').addEventListener('click', callback);
```
You can take advantage of the closure scope in Javascript to pass arguments to callback functions. Check this example:
```js
function callback(a, b) {
return function() {
console.log('sum = ', (a+b));
}
}
var x = 1, y = 2;
document.getElementById('someelem').addEventListener('click', callback(x, y));
```
### What are closures?
Closures are functions that refer to independent (free) variables. In other words, the function defined in the closure 'remembers' the environment in which it was created. [Check MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) to learn more.
So this way the arguments `x` and `y` are in scope of the callback function when it is called.
Another method to do this is using the `bind` method. For example:
```js
var alertText = function(text) {
alert(text);
};
document.getElementById('someelem').addEventListener('click', alertText.bind(this, 'hello'));
```
There is a very slight difference in performance of both methods, checkout [jsperf](http://jsperf.com/bind-vs-closure-23).
================================================
FILE: _posts/en/javascript/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
================================================
---
layout: post
title: Node.js - Run a module if it is not `required`
tip-number: 17
tip-username: odsdq
tip-username-profile: https://twitter.com/odsdq
tip-tldr: In node, you can tell your program to do two different things depending on whether the code is run from `require('./something.js')` or `node something.js`. This is useful if you want to interact with one of your modules independently.
redirect_from:
- /en/nodejs-run-a-module-if-it-is-not-required/
categories:
- en
- javascript
---
In node, you can tell your program to do two different things depending on whether the code is run from `require('./something.js')` or `node something.js`. This is useful if you want to interact with one of your modules independently.
```js
if (!module.parent) {
// ran with `node something.js`
app.listen(8088, function() {
console.log('app listening on port 8088');
})
} else {
// used with `require('/.something.js')`
module.exports = app;
}
```
See [the documentation for modules](https://nodejs.org/api/modules.html#modules_module_parent) for more info.
================================================
FILE: _posts/en/javascript/2016-01-18-rounding-the-fast-way.md
================================================
---
layout: post
title: Truncating the fast (but risky) way
tip-number: 18
tip-username: pklinger
tip-username-profile: https://github.com/pklinger
tip-tldr: .`~~X` is usually a faster `Math.trunc(X)`, but can also make your code do nasty things.
redirect_from:
- /en/rounding-the-fast-way/
categories:
- en
- javascript
---
This tip is about performance...with a hidden price tag.
Have you ever come across the [double tilde `~~` operator](http://stackoverflow.com/questions/5971645/what-is-the-double-tilde-operator-in-javascript)? It's also often called the "double bitwise NOT" operator. You can often use it as a faster substitute for `Math.trunc()`. Why is that?
One bitwise shift `~` first truncates `input` to 32 bits, then transforms it into `-(input+1)`. The double bitwise shift therefore transforms the input into `-(-(input + 1)+1)` making it a great tool to round towards zero. For numeric input, it therefore mimics `Math.trunc()`. On failure, `0` is returned, which might come in handy sometimes instead of `Math.trunc()`, which returns `NaN` on failure.
```js
// single ~
console.log(~1337) // -1338
// numeric input
console.log(~~47.11) // -> 47
console.log(~~1.9999) // -> 1
console.log(~~3) // -> 3
```
However, while `~~` is probably a better performer, experienced programmers often stick with `Math.trunc()` instead. To understand why, here's a clinical view on this operator.
### INDICATIONS
##### When every CPU cycle counts
`~~` is probably faster than `Math.trunc()` across the board, though you should [test that assumption](https://jsperf.com/jsfvsbitnot/10) on whichever platforms matter to you. Also, you'd generally have to perform millions of such operations to have any visible impact at run time.
##### When code clarity is not a concern
If you're trying to confuse others, or get maximum utility from your minifier/uglifier, this is a relatively cheap way to do it.
### CONTRAINDICATIONS
##### When your code needs to be maintained
Code clarity is of great importance in the long term, whether you work in a team, contribute to public code repos, or fly solo. As [the oft-quoted saying](http://c2.com/cgi/wiki?CodeForTheMaintainer) goes:
> Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.
For a solo programmer, that psychopath is inevitably "you in six months".
##### When you forget that `~~` always rounds to zero
Newbie programmers may fixate on the cleverness of `~~`, forgetting the significance of "just drop the fractional portion of this number". This can easily lead to **fencepost errors** (a.k.a. "off-by-one") when transforming floats to array indices or related ordinal values, where a different kind of fractional rounding may actually be called for. (Lack of code clarity usually contributes to this problem.)
For instance, if you're counting numbers on a "nearest integer" basis, you should use `Math.round()` instead of `~~`, but programmer laziness and the impact of **_10 whole characters saved per use_** on human fingers often triumph over cold logic, leading to incorrect results.
In contrast, the very names of the `Math.xyz()` functions clearly communicate their effect, reducing the probability of accidental errors.
##### When dealing with large-magnitude numbers
Because `~` first does a 32-bit conversion, `~~` results in bogus values around ±2.15 billion. If you don't properly range-check your input, a user could trigger unexpected behavior when the transformed value ends up being a great distance from the original:
```js
a = 2147483647.123 // maximum positive 32-bit integer, plus a bit more
console.log(~~a) // -> 2147483647 (ok)
a += 10000 // -> 2147493647.123 (ok)
console.log(~~a) // -> -2147483648 (huh?)
```
One particularly vulnerable area involves dealing with Unix epoch timestamps (measured in seconds from 1 Jan 1970 00:00:00 UTC). A quick way to get such values is:
```js
epoch_int = ~~(+new Date() / 1000) // Date() epochs in milliseconds, so we scale accordingly
```
However, when dealing with timestamps after 19 Jan 2038 03:14:07 UTC (sometimes called the **Y2038 limit**), this breaks horribly:
```js
// epoch timestamp for 1 Jan 2040 00:00:00.123 UTC
epoch = +new Date('2040-01-01') / 1000 + 0.123 // -> 2208988800.123
// back to the future!
epoch_int = ~~epoch // -> -2085978496
console.log(new Date(epoch_int * 1000)) // -> Wed Nov 25 1903 17:31:44 UTC
// that was fun, now let's get real
epoch_flr = Math.floor(epoch) // -> 2208988800
console.log(new Date(epoch_flr * 1000)) // -> Sun Jan 01 2040 00:00:00 UTC
```
##### When the original input wasn't sanitized
Because `~~` transforms every non-number into `0`:
```js
console.log(~~[]) // -> 0
console.log(~~NaN) // -> 0
console.log(~~null) // -> 0
```
some programmers treat it as alternative to proper input validation. However, this can lead to strange logic bugs down the line, since you're no longer distinguishing between invalid inputs and actual `0` values. This is therefore _not_ a recommended practice.
##### When so many people think `~~X == Math.floor(X)`
Most people who write about "double bitwise NOT" incorrectly equate it with `Math.floor()` for some reason. If you can't write about it accurately, odds are good you'll eventually misuse it.
Others are more careful to mention `Math.floor()` for positive inputs and `Math.ceil()` for negative ones, but that forces you to stop and think about the values you're dealing with. This defeats the purpose of `~~` as a handy no-gotchas shortcut.
### DOSAGE
Avoid where possible. Use sparingly otherwise.
### ADMINISTRATION
1. Apply cautiously.
2. Sanitize values before applying.
3. Carefully document relevant assumptions about the values being transformed.
4. Review code to deal with, at minimum:
* logic bugs where invalid inputs are instead passed to other code modules as valid `0` values
* range errors on transformed inputs
* fencepost errors due to incorrect rounding direction
================================================
FILE: _posts/en/javascript/2016-01-19-safe-string-concatenation.md
================================================
---
layout: post
title: Safe string concatenation
tip-number: 19
tip-username: gogainda
tip-username-profile: https://twitter.com/gogainda
tip-tldr: Suppose you have a couple of variables with unknown types and you want to concatenate them in a string. To be sure that the arithmetical operation is not be applied during concatenation, use concat
redirect_from:
- /en/safe-string-concatenation/
categories:
- en
- javascript
---
Suppose you have a couple of variables with unknown types and you want to concatenate them in a string. To be sure that the arithmetical operation is not be applied during concatenation, use `concat`:
```javascript
var one = 1;
var two = 2;
var three = '3';
var result = ''.concat(one, two, three); //"123"
```
This way of concatenting does exactly what you'd expect. In contrast, concatenation with pluses might lead to unexpected results:
```javascript
var one = 1;
var two = 2;
var three = '3';
var result = one + two + three; //"33" instead of "123"
```
Speaking about performance, compared to the `join` [type](http://www.sitepoint.com/javascript-fast-string-concatenation/) of concatenation, the speed of `concat` is pretty much the same.
You can read more about the `concat` function on MDN [page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat).
================================================
FILE: _posts/en/javascript/2016-01-20-return-objects-to-enable-chaining-of-functions.md
================================================
---
layout: post
title: Return objects to enable chaining of functions
tip-number: 20
tip-username: WakeskaterX
tip-username-profile: https://twitter.com/WakeStudio
tip-tldr: When creating functions on an object in Object Oriented Javascript, returning the object in the function will enable you to chain functions together.
redirect_from:
- /en/return-objects-to-enable-chaining-of-functions/
categories:
- en
- javascript
---
When creating functions on an object in Object Oriented Javascript, returning the object in the function will enable you to chain functions together.
```js
function Person(name) {
this.name = name;
this.sayName = function() {
console.log("Hello my name is: ", this.name);
return this;
};
this.changeName = function(name) {
this.name = name;
return this;
};
}
var person = new Person("John");
person.sayName().changeName("Timmy").sayName();
```
================================================
FILE: _posts/en/javascript/2016-01-21-shuffle-an-array.md
================================================
---
layout: post
title: Shuffle an Array
tip-number: 21
tip-username: 0xmtn
tip-username-profile: https://github.com/0xmtn/
tip-tldr: Fisher-Yates Shuffling it's an algorithm to shuffle an array.
redirect_from:
- /en/shuffle-an-array/
categories:
- en
- javascript
---
This snippet here uses [Fisher-Yates Shuffling](https://www.wikiwand.com/en/Fisher%E2%80%93Yates_shuffle) Algorithm to shuffle a given array.
```javascript
function shuffle(arr) {
var i,
j,
temp;
for (i = arr.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
};
```
An example:
```javascript
var a = [1, 2, 3, 4, 5, 6, 7, 8];
var b = shuffle(a);
console.log(b);
// [2, 7, 8, 6, 5, 3, 1, 4]
```
================================================
FILE: _posts/en/javascript/2016-01-22-two-ways-to-empty-an-array.md
================================================
---
layout: post
title: Two ways to empty an array
tip-number: 22
tip-username: microlv
tip-username-profile: https://github.com/microlv
tip-tldr: In JavaScript when you want to empty an array, there are a lot ways, but this is the most performant.
redirect_from:
- /en/two-ways-to-empty-an-array/
categories:
- en
- javascript
---
You define an array and want to empty its contents.
Usually, you would do it like this:
```javascript
// define Array
var list = [1, 2, 3, 4];
function empty() {
//empty your array
list = [];
}
empty();
```
But there is another way to empty an array that is more performant.
You should use code like this:
```javascript
var list = [1, 2, 3, 4];
function empty() {
//empty your array
list.length = 0;
}
empty();
```
* `list = []` assigns a reference to a new array to a variable, while any other references are unaffected.
which means that references to the contents of the previous array are still kept in memory, leading to memory leaks.
* `list.length = 0` deletes everything in the array, which does hit other references.
In other words, if you have two references to the same array (`a = [1,2,3]; a2 = a;`), and you delete the array's contents using `list.length = 0`, both references (a and a2) will now point to the same empty array. (So don't use this technique if you don't want a2 to hold an empty array!)
Think about what this will output:
```js
var foo = [1,2,3];
var bar = [1,2,3];
var foo2 = foo;
var bar2 = bar;
foo = [];
bar.length = 0;
console.log(foo, bar, foo2, bar2);
// [] [] [1, 2, 3] []
```
Stackoverflow more detail:
[difference-between-array-length-0-and-array](http://stackoverflow.com/questions/4804235/difference-between-array-length-0-and-array)
================================================
FILE: _posts/en/javascript/2016-01-23-converting-to-number-fast-way.md
================================================
---
layout: post
title: Converting to number fast way
tip-number: 23
tip-username: sonnyt
tip-username-profile: http://twitter.com/sonnyt
tip-tldr: Converting strings to numbers is extremely common. The easiest and fastest way to achieve that would be using the + operator.
redirect_from:
- /en/converting-to-number-fast-way/
categories:
- en
- javascript
---
Converting strings to numbers is extremely common. The easiest and fastest ([jsPerf](https://jsperf.com/number-vs-parseint-vs-plus/29)) way to achieve that would be using the `+` (plus) operator.
```javascript
var one = '1';
var numberOne = +one; // Number 1
```
You can also use the `-` (minus) operator which type-converts the value into number but also negates it.
```javascript
var one = '1';
var negativeNumberOne = -one; // Number -1
```
================================================
FILE: _posts/en/javascript/2016-01-24-use_===_instead_of_==.md
================================================
---
layout: post
title: Use === instead of ==
tip-number: 24
tip-username: bhaskarmelkani
tip-username-profile: https://www.twitter.com/bhaskarmelkani
tip-tldr: The `==` (or `!=`) operator performs an automatic type conversion if needed. The `===` (or `!==`) operator will not perform any conversion. It compares the value and the type, which could be considered faster ([jsPref](http://jsperf.com/strictcompare)) than `==`.
redirect_from:
- /en/use_===_instead_of_==/
categories:
- en
- javascript
---
The `==` (or `!=`) operator performs an automatic type conversion if needed. The `===` (or `!==`) operator will not perform any conversion. It compares the value and the type, which could be considered faster ([jsPref](http://jsperf.com/strictcompare)) than `==`.
```js
[10] == 10 // is true
[10] === 10 // is false
'10' == 10 // is true
'10' === 10 // is false
[] == 0 // is true
[] === 0 // is false
'' == false // is true but true == "a" is false
'' === false // is false
```
================================================
FILE: _posts/en/javascript/2016-01-25-Using-immediately-invoked-function-expression.md
================================================
---
layout: post
title: Using immediately invoked function expression
tip-number: 25
tip-username: rishantagarwal
tip-username-profile: https://github.com/rishantagarwal
tip-tldr: Called as "Iffy" ( IIFE - immediately invoked function expression) is an anonymous function expression that is immediately invoked and has some important uses in Javascript.
redirect_from:
- /en/Using-immediately-invoked-function-expression/
categories:
- en
- javascript
---
Called as "Iffy" ( IIFE - immediately invoked function expression) is an anonymous function expression that is immediately invoked and has some important uses in Javascript.
```javascript
(function() {
// Do something
}
)()
```
It is an anonymous function expression that is immediately invoked, and it has some particularly important uses in JavaScript.
The pair of parenthesis surrounding the anonymous function turns the anonymous function into a function expression or variable expression. So instead of a simple anonymous function in the global scope, or wherever it was defined, we now have an unnamed function expression.
Similarly, we can even create a named, immediately invoked function expression:
```javascript
(someNamedFunction = function(msg) {
console.log(msg || "Nothing for today !!")
}) (); // Output --> Nothing for today !!
someNamedFunction("Javascript rocks !!"); // Output --> Javascript rocks !!
someNamedFunction(); // Output --> Nothing for today !!
```
For more details, check the following URL's -
1. [Link 1](https://blog.mariusschulz.com/2016/01/13/disassembling-javascripts-iife-syntax)
2. [Link 2](http://javascriptissexy.com/12-simple-yet-powerful-javascript-tips/)
Performance:
[jsPerf](http://jsperf.com/iife-with-call)
================================================
FILE: _posts/en/javascript/2016-01-26-filtering-and-sorting-a-list-of-strings.md
================================================
---
layout: post
title: Filtering and Sorting a List of Strings
tip-number: 26
tip-username: davegomez
tip-username-profile: https://github.com/davegomez
tip-tldr: You may have a big list of names you need to filter in order to remove duplicates and sort them alphabetically.
credirect_from:
- /en/filtering-and-sorting-a-list-of-strings/
categories:
- en
- javascript
---
You may have a big list of names you need to filter in order to remove duplicates and sort them alphabetically.
In our example we are going to use the list of **JavaScript reserved keywords** we can find across the different versions of the language, but as you can notice, there is a lot of duplicated keywords and they are not alphabetically organized. So this is a perfect list ([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)) of strings to test out this JavaScript tip.
```js
var keywords = ['do', 'if', 'in', 'for', 'new', 'try', 'var', 'case', 'else', 'enum', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'delete', 'export', 'import', 'return', 'switch', 'typeof', 'default', 'extends', 'finally', 'continue', 'debugger', 'function', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'var', 'byte', 'case', 'char', 'else', 'enum', 'goto', 'long', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'final', 'float', 'short', 'super', 'throw', 'while', 'delete', 'double', 'export', 'import', 'native', 'public', 'return', 'static', 'switch', 'throws', 'typeof', 'boolean', 'default', 'extends', 'finally', 'package', 'private', 'abstract', 'continue', 'debugger', 'function', 'volatile', 'interface', 'protected', 'transient', 'implements', 'instanceof', 'synchronized', 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof', 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'await', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof'];
```
Since we don't want to change our original list, we are going to use a high order function named [`filter`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), which will return a new filter array based in a predicate (*function*) we pass to it. The predicate will compare the index of the current keyword in the original list with its `index` in the new list and will push it to the new array only if the indexes match.
Finally we are going to sort the filtered list using the [`sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) function which takes a comparison function as the only argument, returning a alphabetically sorted list.
```js
var filteredAndSortedKeywords = keywords
.filter(function (keyword, index) {
return keywords.lastIndexOf(keyword) === index;
})
.sort(function (a, b) {
return a < b ? -1 : 1;
});
```
The **ES6** (ECMAScript 2015) version using [arrow functions](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) looks a little simpler:
```js
const filteredAndSortedKeywords = keywords
.filter((keyword, index) => keywords.lastIndexOf(keyword) === index)
.sort((a, b) => a < b ? -1 : 1);
```
And this is the final filtered and sorted list of JavaScript reserved keywords:
```js
console.log(filteredAndSortedKeywords);
// ['abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void', 'volatile', 'while', 'with', 'yield']
```
*Thanks to [@nikshulipa](https://github.com/nikshulipa), [@kirilloid](https://twitter.com/kirilloid), [@lesterzone](https://twitter.com/lesterzone), [@tracker1](https://twitter.com/tracker1), [@manuel_del_pozo](https://twitter.com/manuel_del_pozo) for all the comments and suggestions!*
================================================
FILE: _posts/en/javascript/2016-01-27-short-circuit-evaluation-in-js.md
================================================
---
layout: post
title: Short circuit evaluation in JS.
tip-number: 27
tip-username: bhaskarmelkani
tip-username-profile: https://www.twitter.com/bhaskarmelkani
tip-tldr: Short-circuit evaluation says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression, when the first argument of the AND `&&` function evaluates to false, the overall value must be false, and when the first argument of the OR `||` function evaluates to true, the overall value must be true.
redirect_from:
- /en/short-circuit-evaluation-in-js/
categories:
- en
- javascript
---
[Short-circuit evaluation](https://en.wikipedia.org/wiki/Short-circuit_evaluation) says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND (`&&`) function evaluates to false, the overall value must be false; and when the first argument of the OR (`||`) function evaluates to true, the overall value must be true.
For the following `test` condition and `isTrue` and `isFalse` function.
```js
var test = true;
var isTrue = function(){
console.log('Test is true.');
};
var isFalse = function(){
console.log('Test is false.');
};
```
Using logical AND - `&&`.
```js
// A normal if statement.
if(test){
isTrue(); // Test is true
}
// Above can be done using '&&' as -
( test && isTrue() ); // Test is true
```
Using logical OR - `||`.
```js
test = false;
if(!test){
isFalse(); // Test is false.
}
( test || isFalse()); // Test is false.
```
The logical OR could also be used to set a default value for function argument.
```js
function theSameOldFoo(name){
name = name || 'Bar' ;
console.log("My best friend's name is " + name);
}
theSameOldFoo(); // My best friend's name is Bar
theSameOldFoo('Bhaskar'); // My best friend's name is Bhaskar
```
The logical AND could be used to avoid exceptions when using properties of undefined.
Example:
```js
var dog = {
bark: function(){
console.log('Woof Woof');
}
};
// Calling dog.bark();
dog.bark(); // Woof Woof.
// But if dog is not defined, dog.bark() will raise an error "Cannot read property 'bark' of undefined."
// To prevent this, we can use &&.
dog&&dog.bark(); // This will only call dog.bark(), if dog is defined.
```
================================================
FILE: _posts/en/javascript/2016-01-28-curry-vs-partial-application.md
================================================
---
layout: post
title: Currying vs partial application
tip-number: 28
tip-username: bhaskarmelkani
tip-username-profile: https://www.twitter.com/bhaskarmelkani
tip-tldr: Currying and partial application are two ways of transforming a function into another function with a generally smaller arity.
redirect_from:
- /en/curry-vs-partial-application/
categories:
- en
- javascript
---
**Currying**
Currying takes a function
f: X * Y -> R
and turns it into a function
f': X -> (Y -> R)
Instead of calling f with two arguments, we invoke f' with the first argument. The result is a function that we then call with the second argument to produce the result.
Thus, if the uncurried f is invoked as
f(3,5)
then the curried f' is invoked as
f(3)(5)
For example:
Uncurried add()
```javascript
function add(x, y) {
return x + y;
}
add(3, 5); // returns 8
```
Curried add()
```javascript
function addC(x) {
return function (y) {
return x + y;
}
}
addC(3)(5); // returns 8
```
**The algorithm for currying.**
Curry takes a binary function and returns a unary function that returns a unary function.
curry: (X × Y → R) → (X → (Y → R))
Javascript Code:
```javascript
function curry(f) {
return function(x) {
return function(y) {
return f(x, y);
}
}
}
```
**Partial application**
Partial application takes a function
f: X * Y -> R
and a fixed value for the first argument to produce a new function
f`: Y -> R
f' does the same as f, but only has to fill in the second parameter which is why its arity is one less than the arity of f.
For example: Binding the first argument of function add to 5 produces the function plus5.
```javascript
function plus5(y) {
return 5 + y;
}
plus5(3); // returns 8
```
**The algorithm of partial application.***
partApply takes a binary function and a value and produces a unary function.
partApply : ((X × Y → R) × X) → (Y → R)
Javascript Code:
```javascript
function partApply(f, x) {
return function(y) {
return f(x, y);
}
}
```
================================================
FILE: _posts/en/javascript/2016-01-29-speed-up-recursive-functions-with-memoization.md
================================================
---
layout: post
title: Speed up recursive functions with memoization
tip-number: 29
tip-username: hingsir
tip-username-profile: https://github.com/hingsir
tip-tldr: Fibonacci sequence is very familiar to everybody. we can write the following function in 20 seconds.it works, but not efficient. it did lots of duplicate computing works, we can cache its previously computed results to speed it up.
redirect_from:
- /en/speed-up-recursive-functions-with-memoization/
categories:
- en
- javascript
---
Fibonacci sequence is very familiar to everybody. We can write the following function in 20 seconds.
```js
var fibonacci = function(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
```
It works, but is not efficient. It did lots of duplicate computing works, we can cache its previously computed results to speed it up.
```js
var fibonacci = (function() {
var cache = [0, 1]; // cache the value at the n index
return function(n) {
if (cache[n] === undefined) {
for (var i = cache.length; i <= n; ++i) {
cache[i] = cache[i - 1] + cache[i - 2];
}
}
return cache[n];
}
})();
```
Also, we can define a higher-order function that accepts a function as its argument and returns a memoized version of the function.
```js
var memoize = function(func) {
var cache = {};
return function() {
var key = JSON.stringify(Array.prototype.slice.call(arguments));
return key in cache ? cache[key] : (cache[key] = func.apply(this, arguments));
}
}
fibonacci = memoize(fibonacci);
```
And this is an ES6 version of the memoize function.
```js
var memoize = function(func) {
const cache = {};
return (...args) => {
const key = JSON.stringify(args);
return key in cache ? cache[key] : (cache[key] = func(...args));
}
}
fibonacci = memoize(fibonacci);
```
we can use `memoize()` in many other situations
* GCD(Greatest Common Divisor)
```js
var gcd = memoize(function(a, b) {
var t;
if (a < b) t = b, b = a, a = t;
while (b != 0) t = b, b = a % b, a = t;
return a;
});
gcd(27, 183); //=> 3
```
* Factorial calculation
```js
var factorial = memoize(function(n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
})
factorial(5); //=> 120
```
Learn more about memoization:
- [Memoization - Wikipedia](https://en.wikipedia.org/wiki/Memoization)
- [Implementing Memoization in JavaScript](https://www.sitepoint.com/implementing-memoization-in-javascript/)
================================================
FILE: _posts/en/javascript/2016-01-30-converting-truthy-falsy-values-to-boolean.md
================================================
---
layout: post
title: Converting truthy/falsy values to boolean
tip-number: 30
tip-username: hakhag
tip-username-profile: https://github.com/hakhag
tip-tldr: Logical operators are a core part of JavaScript, here you can see a a way you always get a true or false no matter what was given to it.
redirect_from:
- /en/converting-truthy-falsy-values-to-boolean/
categories:
- en
- javascript
---
You can convert a [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) or [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) value to true boolean with the `!!` operator.
```js
!!"" // false
!!0 // false
!!null // false
!!undefined // false
!!NaN // false
!!"hello" // true
!!1 // true
!!{} // true
!![] // true
```
================================================
FILE: _posts/en/javascript/2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
================================================
---
layout: post
title: Avoid modifying or passing `arguments` into other functions — it kills optimization
tip-number: 31
tip-username: berkana
tip-username-profile: https://github.com/berkana
tip-tldr: Within JavaScript functions, the variable name `arguments` lets you access all of the arguments passed to the function. `arguments` is an *array-like object*; `arguments` can be accessed using array notation, and it has the *length* property, but it doesn't have many of the built-in methods that arrays have such as `filter` and `map` and `forEach`. Because of this, it is a fairly common practice to convert `arguments` into an array using the following snipet
redirect_from:
- /en/avoid-modifying-or-passing-arguments-into-other-functions-it-kills-optimization/
categories:
- en
- javascript
---
###Background
Within JavaScript functions, the variable name [`arguments`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) lets you access all of the arguments passed to the function. `arguments` is an *array-like object*; `arguments` can be accessed using array notation, and it has the *length* property, but it doesn't have many of the built-in methods that arrays have such as `filter` and `map` and `forEach`. Because of this, it is a fairly common practice to convert `arguments` into an array using the following:
```js
var args = Array.prototype.slice.call(arguments);
```
This calls the `slice` method from the `Array` prototype, passing it `arguments`; the `slice` method returns a shallow copy of `arguments` as a new array object. A common shorthand for this is :
```js
var args = [].slice.call(arguments);
```
In this case, instead of calling `slice` from the `Array` prototype, it is simply being called from an empty array literal.
###Optimization
Unfortunately, passing `arguments` into any function call will cause the V8 JavaScript engine used in Chrome and Node to skip optimization on the function that does this, which can result in considerably slower performance. See this article on [optimization killers](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers). Passing `arguments` to any other function is known as *leaking `arguments`*.
Instead, if you want an array of the arguments that lets you use you need to resort to this:
```js
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
```
Yes it is more verbose, but in production code, it is worth it for the performance optimization.
================================================
FILE: _posts/en/javascript/2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
================================================
---
layout: post
title: Map() to the rescue; adding order to Object properties
tip-number: 32
tip-username: loverajoel
tip-username-profile: https://twitter.com/loverajoel
tip-tldr: An Object it is an unordered collection of properties... that means that if you are trying to save ordered data inside an Object, you have to review it because properties order in objects are not guaranteed.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/map-to-the-rescue-adding-order-to-object-properties/
categories:
- en
- javascript
---
## Object properties order
> An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method. [ECMAScript](http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf)
Take a look in action
```js
var myObject = {
z: 1,
'@': 2,
b: 3,
1: 4,
5: 5
};
console.log(myObject) // Object {1: 4, 5: 5, z: 1, @: 2, b: 3}
for (item in myObject) {...
// 1
// 5
// z
// @
// b
```
Each browser have his own rules about the order in objects bebause technically, order is unspecified.
## How to solve this?
### Map
Using a new ES6 feature called Map. A [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) object iterates its elements in insertion order — a `for...of` loop returns an array of [key, value] for each iteration.
```js
var myObject = new Map();
myObject.set('z', 1);
myObject.set('@', 2);
myObject.set('b', 3);
for (var [key, value] of myObject) {
console.log(key, value);
...
// z 1
// @ 2
// b 3
```
### Hack for old browsers
Mozilla suggest:
> So, if you want to simulate an ordered associative array in a cross-browser environment, you are forced to either use two separate arrays (one for the keys and the other for the values), or build an array of single-property objects, etc.
```js
// Using two separate arrays
var objectKeys = [z, @, b, 1, 5];
for (item in objectKeys) {
myObject[item]
...
// Build an array of single-property objects
var myData = [{z: 1}, {'@': 2}, {b: 3}, {1: 4}, {5: 5}];
```
================================================
FILE: _posts/en/javascript/2016-02-02-create-range-0-n-easily-using-one-line.md
================================================
---
layout: post
title: Create array sequence `[0, 1, ..., N-1]` in one line
tip-number: 33
tip-username: SarjuHansaliya
tip-username-profile: https://github.com/SarjuHansaliya
tip-tldr: Compact one-liners that generate ordinal sequence arrays
redirect_from:
- /en/create-range-0-n-easily-using-one-line/
categories:
- en
- javascript
---
Here are two compact code sequences to generate the `N`-element array `[0, 1, ..., N-1]`:
### Solution 1 (requires ES5)
```js
Array.apply(null, {length: N}).map(Function.call, Number);
```
#### Brief explanation
1. `Array.apply(null, {length: N})` returns an `N`-element array filled with `undefined` (i.e. `A = [undefined, undefined, ...]`).
2. `A.map(Function.call, Number)` returns an `N`-element array, whose index `I` gets the result of `Function.call.call(Number, undefined, I, A)`
3. `Function.call.call(Number, undefined, I, A)` collapses into `Number(I)`, which is naturally `I`.
4. Result: `[0, 1, ..., N-1]`.
For a more thorough explanation, go [here](https://github.com/gromgit/jstips-xe/blob/master/tips/33.md).
### Solution 2 (requires ES6)
It uses `Array.from` [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
```js
Array.from(new Array(N),(val,index)=>index);
```
### Solution 3 (requires ES6)
```js
Array.from(Array(N).keys());
```
#### Brief explanation
1. `A = new Array(N)` returns an array with `N` _holes_ (i.e. `A = [,,,...]`, but `A[x] = undefined` for `x` in `0...N-1`).
2. `F = (val,index)=>index` is simply `function F (val, index) { return index; }`
3. `Array.from(A, F)` returns an `N`-element array, whose index `I` gets the results of `F(A[I], I)`, which is simply `I`.
4. Result: `[0, 1, ..., N-1]`.
### One More Thing
If you actually want the sequence [1, 2, ..., N], **Solution 1** becomes:
```js
Array.apply(null, {length: N}).map(function(value, index){
return index + 1;
});
```
and **Solution 2**:
```js
Array.from(new Array(N),(val,index)=>index+1);
```
================================================
FILE: _posts/en/javascript/2016-02-03-implementing-asynchronous-loops.md
================================================
---
layout: post
title: Implementing asynchronous loop
tip-number: 34
tip-username: madmantalking
tip-username-profile: https://github.com/madmantalking
tip-tldr: You may run into problems while implementing asynchronous loops.
redirect_from:
- /en/implementing-asynchronous-loops/
categories:
- en
- javascript
---
Let's try out writing an asynchronous function which prints the value of the loop index every second.
```js
for (var i=0; i<5; i++) {
setTimeout(function(){
console.log(i);
}, 1000 * (i+1));
}
```
The output of the above programs turns out to be
```js
> 5
> 5
> 5
> 5
> 5
```
So this definitely doesn't work.
**Reason**
Each timeout refers to the original `i`, not a copy. So the for loop increments `i` until it gets to 5, then the timeouts run and use the current value of `i` (which is 5).
Well , this problem seems easy. An immediate solution that strikes is to cache the loop index in a temporary variable.
```js
for (var i=0; i<5; i++) {
var temp = i;
setTimeout(function(){
console.log(temp);
}, 1000 * (i+1));
}
```
But again the output of the above programs turns out to be
```js
> 4
> 4
> 4
> 4
> 4
```
So , that doesn't work either , because blocks don't create a scope and variables initializers are hoisted to the top of the scope. In fact, the previous block is the same as:
```js
var temp;
for (var i=0; i<5; i++) {
temp = i;
setTimeout(function(){
console.log(temp);
}, 1000 * (i+1));
}
```
**Solution**
There are a few different ways to copy `i`. The most common way is creating a closure by declaring a function and passing `i` as an argument. Here we do this as a self-calling function.
```js
for (var i=0; i<5; i++) {
(function(num){
setTimeout(function(){
console.log(num);
}, 1000 * (i+1));
})(i);
}
```
In JavaScript, arguments are passed by value to a function. So primitive types like numbers, dates, and strings are basically copied. If you change them inside the function, it does not affect the outside scope. Objects are special: if the inside function changes a property, the change is reflected in all scopes.
Another approach for this would be with using `let`. With ES6 the `let` keyword is useful since it's block scoped unlike `var`
```js
for (let i=0; i<5; i++) {
setTimeout(function(){
console.log(i);
}, 1000 * (i+1));
}
```
================================================
FILE: _posts/en/javascript/2016-02-04-assignment-shorthands.md
================================================
---
layout: post
title: Assignment Operators
tip-number: 35
tip-username: hsleonis
tip-username-profile: https://github.com/hsleonis
tip-tldr: Assigning is very common. Sometimes typing becomes time consuming for us 'Lazy programmers'. So, we can use some tricks to help us and make our code cleaner and simpler.
redirect_from:
- /en/assignment-shorthands/
categories:
- en
- javascript
---
Assigning is very common. Sometimes typing becomes time consuming for us 'Lazy programmers'.
So, we can use some tricks to help us and make our code cleaner and simpler.
This is the similar use of
````javascript
x += 23; // x = x + 23;
y -= 15; // y = y - 15;
z *= 10; // z = z * 10;
k /= 7; // k = k / 7;
p %= 3; // p = p % 3;
d **= 2; // d = d ** 2;
m >>= 2; // m = m >> 2;
n <<= 2; // n = n << 2;
n ++; // n = n + 1;
n --; n = n - 1;
````
### `++` and `--` operators
There is a special `++` operator. It's best to explain it with an example:
````javascript
var a = 2;
var b = a++;
// Now a is 3 and b is 2
````
The `a++` statement does this:
1. return the value of `a`
2. increment `a` by 1
But what if we wanted to increment the value first? It's simple:
````javascript
var a = 2;
var b = ++a;
// Now both a and b are 3
````
See? I put the operator _before_ the variable.
The `--` operator is similar, except it decrements the value.
### If-else (Using ternary operator)
This is what we write on regular basis.
````javascript
var newValue;
if(value > 10)
newValue = 5;
else
newValue = 2;
````
We can user ternary operator to make it awesome:
````javascript
var newValue = (value > 10) ? 5 : 2;
````
### Null, Undefined, Empty Checks
````javascript
if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
var variable2 = variable1;
}
````
Shorthand here:
````javascript
var variable2 = variable1 || '';
````
P.S.: If variable1 is a number, then first check if it is 0.
### Object Array Notation
Instead of using:
````javascript
var a = new Array();
a[0] = "myString1";
a[1] = "myString2";
````
Use this:
````javascript
var a = ["myString1", "myString2"];
````
### Associative array
Instead of using:
````javascript
var skillSet = new Array();
skillSet['Document language'] = 'HTML5';
skillSet['Styling language'] = 'CSS3';
````
Use this:
````javascript
var skillSet = {
'Document language' : 'HTML5',
'Styling language' : 'CSS3'
};
````
================================================
FILE: _posts/en/javascript/2016-02-05-observe-dom-changes.md
================================================
---
layout: post
title: Observe DOM changes in extensions
tip-number: 36
tip-username: beyondns
tip-username-profile: https://github.com/beyondns
tip-tldr: When you develop extensions to existent sites it's not so easy to play with DOM 'cause of modern dynamic javascript.
redirect_from:
- /en/observe-dom-changes/
categories:
- en
- javascript
---
[MutationObserver](https://developer.mozilla.org/en/docs/Web/API/MutationObserver) is a solution to listen DOM changes and do what you want to do with elements when they changed. In following example there is some emulation of dynamic content loading with help of timers, after first "target" element creation goes "subTarget".
In extension code firstly rootObserver works till targetElement appearance then elementObserver starts. This cascading observing helps finally get moment when subTargetElement found.
This useful to develop extensions to complex sites with dynamic content loading.
```js
const observeConfig = {
attributes: true,
childList: true,
characterData: true,
subtree: true
};
function initExtension(rootElement, targetSelector, subTargetSelector) {
var rootObserver = new MutationObserver(function(mutations) {
console.log("Inside root observer");
targetElement = rootElement.querySelector(targetSelector);
if (targetElement) {
rootObserver.disconnect();
var elementObserver = new MutationObserver(function(mutations) {
console.log("Inside element observer");
subTargetElement = targetElement.querySelector(subTargetSelector);
if (subTargetElement) {
elementObserver.disconnect();
console.log("subTargetElement found!");
}
});
elementObserver.observe(targetElement, observeConfig);
}
});
rootObserver.observe(rootElement, observeConfig);
}
(function() {
initExtension(document.body, "div.target", "div.subtarget");
setTimeout(function() {
del = document.createElement("div");
del.innerHTML = "<div class='target'>target</div>";
document.body.appendChild(del);
}, 3000);
setTimeout(function() {
var el = document.body.querySelector('div.target');
if (el) {
del = document.createElement("div");
del.innerHTML = "<div class='subtarget'>subtarget</div>";
el.appendChild(del);
}
}, 5000);
})();
```
================================================
FILE: _posts/en/javascript/2016-02-06-deduplicate-an-array.md
================================================
---
layout: post
title: Deduplicate an Array
tip-number: 37
tip-username: danillouz
tip-username-profile: https://www.twitter.com/danillouz
tip-tldr: How to remove duplicate elements, of different data types, from an Array.
redirect_from:
- /en/deduplicate-an-array/
categories:
- en
- javascript
---
# Primitives
If an Array only contains primitive values, we can deduplicate it by
only using the [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) and [`indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) methods.
```javascript
var deduped = [ 1, 1, 'a', 'a' ].filter(function (el, i, arr) {
return arr.indexOf(el) === i;
});
console.log(deduped); // [ 1, 'a' ]
```
## ES2015
We can write this in a more compact way using an [arrow function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions).
```javascript
var deduped = [ 1, 1, 'a', 'a' ].filter( (el, i, arr) => arr.indexOf(el) === i);
console.log(deduped); // [ 1, 'a' ]
```
But with the introduction of [Sets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) and the [`from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) method, we can achieve the same
result in a more concise way.
```javascript
var deduped = Array.from( new Set([ 1, 1, 'a', 'a' ]) );
console.log(deduped); // [ 1, 'a' ]
```
# Objects
We can't use the same approach when the elements are Objects,
because Objects are stored by reference and primitives are stored
by value.
```javascript
1 === 1 // true
'a' === 'a' // true
{ a: 1 } === { a: 1 } // false
```
Therefore we need to change our approach and use a hash table.
```javascript
function dedup(arr) {
var hashTable = {};
return arr.filter(function (el) {
var key = JSON.stringify(el);
var match = Boolean(hashTable[key]);
return (match ? false : hashTable[key] = true);
});
}
var deduped = dedup([
{ a: 1 },
{ a: 1 },
[ 1, 2 ],
[ 1, 2 ]
]);
console.log(deduped); // [ {a: 1}, [1, 2] ]
```
Because a hash table in javascript is simply an `Object`, the keys
will always be of the type `String`. This means that normally we can't
distinguish between strings and numbers of the same value, i.e. `1` and
`'1'`.
```javascript
var hashTable = {};
hashTable[1] = true;
hashTable['1'] = true;
console.log(hashTable); // { '1': true }
```
However, because we're using [`JSON.stringify`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), keys that are of the
type `String`, will be stored as an escaped string value, giving us unique
keys in our `hashTable`.
```javascript
var hashTable = {};
hashTable[JSON.stringify(1)] = true;
hashTable[JSON.stringify('1')] = true;
console.log(hashTable); // { '1': true, '\'1\'': true }
```
This means duplicate elements of the same value, but of a different type,
will still be deduplicated using the same implementation.
```javascript
var deduped = dedup([
{ a: 1 },
{ a: 1 },
[ 1, 2 ],
[ 1, 2 ],
1,
1,
'1',
'1'
]);
console.log(deduped); // [ {a: 1}, [1, 2], 1, '1' ]
```
# Resources
## Methods
* [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
* [`indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)
* [`from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
* [`JSON.stringify`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
## ES2015
* [arrow functions](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
* [Sets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
## Stack overflow
* [remove duplicates from array](http://stackoverflow.com/questions/9229645/remove-duplicates-from-javascript-array/9229821#9229821)
================================================
FILE: _posts/en/javascript/2016-02-07-flattening-multidimensional-arrays-in-javascript.md
================================================
---
layout: post
title: Flattening multidimensional Arrays in JavaScript
tip-number: 38
tip-username: loverajoel
tip-username-profile: https://www.twitter.com/loverajoel
tip-tldr: Three different solutions to merge multidimensional array into a single array.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/flattening-multidimensional-arrays-in-javascript/
categories:
- en
- javascript
---
These are the three known ways to merge multidimensional array into a single array.
Given this array:
```js
var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
```
We wanna have this result:
```js
[1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### Solution 1: Using [`concat()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) and [`apply()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
```js
var myNewArray = [].concat.apply([], myArray);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### Solution 2: Using [`reduce()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Flatten_an_array_of_arrays)
```js
var myNewArray = myArray.reduce(function(prev, curr) {
return prev.concat(curr);
});
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### Solution 3:
```js
var myNewArray3 = [];
for (var i = 0; i < myArray.length; ++i) {
for (var j = 0; j < myArray[i].length; ++j)
myNewArray3.push(myArray[i][j]);
}
console.log(myNewArray3);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### Solution 4: Using [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) in ES6
```js
var myNewArray4 = [].concat(...myArray);
console.log(myNewArray4);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### Solution 5: Using [`flat()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) in ES10
```js
var myNewArray5 = myArray.flat();
console.log(myNewArray5);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
Take a look [here](https://jsbin.com/janana/edit?js,console) these 4 algorithms in action.
For infinitely nested array try Lodash [flattenDeep()](https://lodash.com/docs#flattenDeep).
If you are curious about performance, [here](http://jsperf.com/flatten-an-array-loop-vs-reduce/6) a test for check how it works.
================================================
FILE: _posts/en/javascript/2016-02-08-advanced-properties.md
================================================
---
layout: post
title: Advanced Javascript Properties
tip-number: 39
tip-username: mallowigi
tip-username-profile: https://github.com/mallowigi
tip-tldr: How to add private properties, getters and setters to objects.
redirect_from:
- /en/advanced-properties/
categories:
- en
- javascript
---
It is possible to configure object properties in Javascript for example to set properties to be pseudo-private or readonly. This feature is available since ECMAScript 5.1, therefore supported by all recent browsers.
To do so, you need to use the method `defineProperty` of the `Object` prototype like so:
```js
var a = {};
Object.defineProperty(a, 'readonly', {
value: 15,
writable: false
});
a.readonly = 20;
console.log(a.readonly); // 15
```
The syntax is as follows:
```js
Object.defineProperty(dest, propName, options)
```
or for multiple definitions:
```js
Object.defineProperties(dest, {
propA: optionsA,
propB: optionsB, //...
})
```
where options include the following attributes:
- *value*: if the property is not a getter (see below), value is a mandatory attribute. `{a: 12}` === `Object.defineProperty(obj, 'a', {value: 12})`
- *writable*: set the property as readonly. Note that if the property is a nested objects, its properties are still editable.
- *enumerable*: set the property as hidden. That means that `for ... of` loops and `stringify` will not include the property in their result, but the property is still there. Note: That doesn't mean that the property is private! It can still be accessible from the outside, it just means that it won't be printed.
- *configurable*: set the property as non modifiable, e.g. protected from deletion or redefinition. Again, if the property is a nested object, its properties are still configurable.
So in order to create a private constant property, you can define it like so:
```js
Object.defineProperty(obj, 'myPrivateProp', {value: val, enumerable: false, writable: false, configurable: false});
```
Besides configuring properties, `defineProperty` allows us to define *dynamic properties*, thanks to the second parameter being a string. For instance, let's say that I want to create properties according to some external configuration:
```js
var obj = {
getTypeFromExternal(): true // illegal in ES5.1
}
Object.defineProperty(obj, getTypeFromExternal(), {value: true}); // ok
// For the example sake, ES6 introduced a new syntax:
var obj = {
[getTypeFromExternal()]: true
}
```
But that's not all! Advanced properties allows us to create **getters** and **setters**, just like other OOP languages! In that case, one cannot use the `writable`, `enumerable` and `configurable` properties, but instead:
```js
function Foobar () {
var _foo; // true private property
Object.defineProperty(obj, 'foo', {
get: function () { return _foo; }
set: function (value) { _foo = value }
});
}
var foobar = new Foobar();
foobar.foo; // 15
foobar.foo = 20; // _foo = 20
```
Aside for the obvious advantage of encapsulation and advanced accessors, you will notice that we didn't "call" the getter, instead we just "get" the property without parentheses! This is awesome! For instance, let's imagine that we have an object with long nested properties, like so:
```js
var obj = {a: {b: {c: [{d: 10}, {d: 20}] } } };
```
Now instead of doing `a.b.c[0].d` (where one of the properties can resolve to `undefined` and throw an error), we can instead create an alias:
```js
Object.defineProperty(obj, 'firstD', {
get: function () { return a && a.b && a.b.c && a.b.c[0] && a.b.c[0].d }
})
console.log(obj.firstD) // 10
```
### Note
If you define a getter without a setter and still try to set a value, you will get an error! This is particularly important when using helper functions such as `$.extend` or `_.merge`. Be careful!
### Links
- [defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty)
- [Defining properties in JavaScript](http://bdadam.com/blog/defining-properties-in-javascript.html)
================================================
FILE: _posts/en/javascript/2016-02-09-using-json-stringify.md
================================================
---
layout: post
title: Using JSON.Stringify
tip-number: 40
tip-username: vamshisuram
tip-username-profile: https://github.com/vamshisuram
tip-tldr: Create string from selected properties of JSON object.
redirect_from:
- /en/using-json-stringify/
categories:
- en
- javascript
---
Let's say there is an object with properties "prop1", "prop2", "prop3".
We can pass __additional params__ to __JSON.stringify__ to selectively write properties of the object to string like:
```javascript
var obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};
var selectedProperties = ['prop1', 'prop2'];
var str = JSON.stringify(obj, selectedProperties);
// str
// {"prop1":"value1","prop2":"value2"}
```
The __"str"__ will contain only info on selected properties only.
Instead of array we can pass a function also.
```javascript
function selectedProperties(key, val) {
// the first val will be the entire object, key is empty string
if (!key) {
return val;
}
if (key === 'prop1' || key === 'prop2') {
return val;
}
return;
}
```
The last optional param it takes is to modify the way it writes the object to string.
```javascript
var str = JSON.stringify(obj, selectedProperties, '\t\t');
/* str output with double tabs in every line.
{
"prop1": "value1",
"prop2": "value2"
}
*/
```
================================================
FILE: _posts/en/javascript/2016-02-10-array-average-and-median.md
================================================
---
layout: post
title: Array average and median
tip-number: 41
tip-username: soyuka
tip-username-profile: https://github.com/soyuka
tip-tldr: Calculate the average and median from array values
redirect_from:
- /en/array-average-and-median/
categories:
- en
- javascript
---
The following examples will be based on the following array:
```javascript
let values = [2, 56, 3, 41, 0, 4, 100, 23];
```
To get the average, we have to sum up numbers and then divide by the number of values. Steps are:
- get the array length
- sum up values
- get the average (`sum/length`)
```javascript
let values = [2, 56, 3, 41, 0, 4, 100, 23];
let sum = values.reduce((previous, current) => current += previous);
let avg = sum / values.length;
// avg = 28
```
Or:
```javascript
let values = [2, 56, 3, 41, 0, 4, 100, 23];
let count = values.length;
values = values.reduce((previous, current) => current += previous);
values /= count;
// avg = 28
```
Now, to get the median steps are:
- sort the array
- get the arethmic mean of the middle values
```javascript
let values = [2, 56, 3, 41, 0, 4, 100, 23];
values.sort((a, b) => a - b);
let lowMiddle = Math.floor((values.length - 1) / 2);
let highMiddle = Math.ceil((values.length - 1) / 2);
let median = (values[lowMiddle] + values[highMiddle]) / 2;
// median = 13,5
```
With a bitwise operator:
```javascript
let values = [2, 56, 3, 41, 0, 4, 100, 23];
values.sort((a, b) => a - b);
let median = (values[(values.length - 1) >> 1] + values[values.length >> 1]) / 2
// median = 13,5
```
================================================
FILE: _posts/en/javascript/2016-02-11-preventing-unapply-attacks.md
================================================
---
layout: post
title: Preventing Unapply Attacks
tip-number: 42
tip-username: emars
tip-username-profile: https://twitter.com/marseltov
tip-tldr: Freeze the builtin prototypes.
redirect_from:
- /en/preventing-unapply-attacks/
categories:
- en
- javascript
---
By overriding the builtin prototypes, external code can cause code to break by rewriting code to expose and change bound arguments. This can be an issue that seriously breaks applications that works by using polyfill es5 methods.
```js
// example bind polyfill
function bind(fn) {
var prev = Array.prototype.slice.call(arguments, 1);
return function bound() {
var curr = Array.prototype.slice.call(arguments, 0);
var args = Array.prototype.concat.apply(prev, curr);
return fn.apply(null, args);
};
}
// unapply-attack
function unapplyAttack() {
var concat = Array.prototype.concat;
Array.prototype.concat = function replaceAll() {
Array.prototype.concat = concat; // restore the correct version
var curr = Array.prototype.slice.call(arguments, 0);
var result = concat.apply([], curr);
return result;
};
}
```
The above function discards the `prev` array from the bind meaning that any `.concat` the first concat call following using the unapply attack will throw an error.
By using [Object.freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), making an object immutable, you prevent any overriding of the builtin object prototypes.
```js
(function freezePrototypes() {
if (typeof Object.freeze !== 'function') {
throw new Error('Missing Object.freeze');
}
Object.freeze(Object.prototype);
Object.freeze(Array.prototype);
Object.freeze(Function.prototype);
}());
```
You can read more about unapply attacks [here](https://glebbahmutov.com/blog/unapply-attack/).
Although this concept is called an 'unapply attack' due to some code being able to access closures that normally wouldn't be in scope, it is mostly wrong to consider this a security feature due to it not preventing an attacker with code execution from extending prototypes before the freezing happens and also still having the potential to read all scopes using various language features. ECMA modules would give realm based isolation which is much stronger than this solution however still doesn't fix the issues of third party scripts.
================================================
FILE: _posts/en/javascript/2016-02-12-use-destructuring-in-function-parameters.md
================================================
---
layout: post
title: Use destructuring in function parameters
tip-number: 43
tip-username: dislick
tip-username-profile: https://github.com/dislick
tip-tldr: Did you know that you can use destructuring in function parameters?
redirect_from:
- /en/use-destructuring-in-function-parameters/
categories:
- en
- javascript
---
I am sure many of you are already familiar with the [ES6 Destructuring Assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). Did you know that you can also use it in function parameters?
```js
var sayHello = function({ name, surname }) {
console.log(`Hello ${name} ${surname}! How are you?`);
};
sayHello({ name: 'John', surname: 'Smith' })
// -> Hello John Smith! How are you?
```
This is great for functions which accept an options object. For this use case, you can also add [default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) to fill in whatever values the caller leaves out, or if the caller forgets to pass one at all:
```js
var sayHello2 = function({ name = "Anony", surname = "Moose" } = {}) {
console.log(`Hello ${name} ${surname}! How are you?`);
};
```
The `= {}` says that the default object to be destructured for this parameter is `{}`, in case the caller forgets to pass the parameter, or passes one of the wrong type (more on this below).
```js
sayHello2()
// -> Hello Anony Moose! How are you?
sayHello2({ name: "Bull" })
// -> Hello Bull Moose! How are you?
```
##### Argument Handling
With plain destructuring assignment, if the the input parameter can't be matched with the function's specified object arguments, all the unmatched arguments are `undefined`, so you need to add code that handles this properly:
```js
var sayHelloTimes = function({ name, surname }, times) {
console.log(`Hello ${name} ${surname}! I've seen you ${times} times before.`);
}
sayHelloTimes({ name: "Pam" }, 5678)
// -> Hello Pam undefined! I've seen you 5678 times before.
sayHelloTimes(5678)
// -> Hello undefined undefined! I've seen you undefined times before.
```
Worse, if the parameter to be destructured is missing, an exception is thrown, probably bringing your app to a screeching halt:
```js
sayHelloTimes()
// -> Uncaught TypeError: Cannot match against 'undefined' or 'null'...
```
It's conceptually similar to accessing a property of an undefined object, just with a different exception type.
Destructuring assignment with default parameters hides all the above to a certain extent:
```js
var sayHelloTimes2 = function({ name = "Anony", surname = "Moose" } = {}, times) {
console.log(`Hello ${name} ${surname}! I've seen you ${times} times before.`);
};
sayHelloTimes2({ name: "Pam" }, 5678)
// -> Hello Pam Moose! I've seen you 5678 times before.
sayHelloTimes2(5678)
// -> Hello Anony Moose! I've seen you undefined times before.
sayHelloTimes2()
// -> Hello Anony Moose! I've seen you undefined times before.
```
As for `= {}`, it covers the case of a missing _object_, for which individual property defaults won't help at all:
```js
var sayHelloTimes2a = function({ name = "Anony", surname = "Moose" }, times) {
console.log(`Hello ${name} ${surname}! I've seen you ${times} times before.`);
};
sayHelloTimes2a({ name: "Pam" }, 5678)
// -> Hello Pam Moose! I've seen you 5678 times before.
sayHelloTimes2a(5678)
// -> Hello Anony Moose! I've seen you undefined times before.
sayHelloTimes2a()
// -> Uncaught TypeError: Cannot match against 'undefined' or 'null'.
```
##### Availability
Note that destructuring assignment may not yet be available by default, in the version of Node.js or browser that you're using. For Node.js, you can try using the `--harmony-destructuring` flag on startup to activate this feature.
================================================
FILE: _posts/en/javascript/2016-02-13-know-the-passing-mechanism.md
================================================
---
layout: post
title: Know the passing mechanism
tip-number: 44
tip-username: bmkmanoj
tip-username-profile: https://github.com/bmkmanoj
tip-tldr: JavaScript technically only passes by value for both primitives and object (or reference) types. In case of reference types the reference value itself is passed by value.
redirect_from:
- /en/know-the-passing-mechanism/
categories:
- en
- javascript
---
JavaScript is pass-by-value, technically. It is neither pass-by-value nor pass-by-reference, going by the truest sense of these terms. To understand this passing mechanism, take a look at the following two example code snippets and the explanations.
### Example 1
```js
var me = { // 1
'partOf' : 'A Team'
};
function myTeam(me) { // 2
me = { // 3
'belongsTo' : 'A Group'
};
}
myTeam(me);
console.log(me); // 4 : {'partOf' : 'A Team'}
```
In above example, when the `myTeam` gets invoked, JavaScript is *passing the reference to* `me` *object as value, as it is an object* and invocation itself creates two independent references to the same object, (though the name being same here i.e. `me`, is misleading and gives us an impression that it is the single reference) and hence, the reference variable themselves are independent.
When we assigned a new object at #`3`, we are changing this reference value entirely within the `myTeam` function, and it will not have any impact on the original object outside this function scope, from where it was passed and the reference in the outside scope is going to retain the original object and hence the output from #`4`.
### Example 2
```js
var me = { // 1
'partOf' : 'A Team'
};
function myGroup(me) { // 2
me.partOf = 'A Group'; // 3
}
myGroup(me);
console.log(me); // 4 : {'partOf' : 'A Group'}
```
In the case of `myGroup` invocation, we are passing the object `me`. But unlike the example 1 scenario, we are not assigning this `me` variable to any new object, effectively meaning the object reference value within the `myGroup` function scope still is the original object's reference value and when we are modifying the property within this scope, it is effectively modifying the original object's property. Hence, you get the output from #`4`.
So does this later case not prove that javascript is pass-by-reference? No, it does not. Remember, *JavaScript passes the reference as value, in case of objects*. The confusion arises as we tend not to understand fully what pass by reference is. This is the exact reason, some prefer to call this as *call-by-sharing*.
*Initially posted by the author on [js-by-examples](https://github.com/bmkmanoj/js-by-examples/blob/master/examples/js_pass_by_value_or_reference.md)*
================================================
FILE: _posts/en/javascript/2016-02-14-calculate-the-max-min-value-from-an-array.md
================================================
---
layout: post
title: Calculate the Max/Min value from an array
tip-number: 45
tip-username: loverajoel
tip-username-profile: https://www.twitter.com/loverajoel
tip-tldr: Ways to use the built-in functions Math.max() and Math.min() with arrays of numbers
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/calculate-the-max-min-value-from-an-array/
categories:
- en
- javascript
---
The built-in functions [Math.max()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max) and [Math.min()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min) find the maximum and minimum value of the arguments, respectively.
```js
Math.max(1, 2, 3, 4); // 4
Math.min(1, 2, 3, 4); // 1
```
These functions will not work as-is with arrays of numbers. However, there are some ways around this.
[`Function.prototype.apply()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) allows you to call a function with a given `this` value and an _array_ of arguments.
```js
var numbers = [1, 2, 3, 4];
Math.max.apply(null, numbers) // 4
Math.min.apply(null, numbers) // 1
```
Passing the `numbers` array as the second argument of `apply()` results in the function being called with all values in the array as parameters.
A simpler, ES2015 way of accomplishing this is with the new [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).
```js
var numbers = [1, 2, 3, 4];
Math.max(...numbers) // 4
Math.min(...numbers) // 1
```
This operator causes the values in the array to be expanded, or "spread", into the function's arguments.
================================================
FILE: _posts/en/javascript/2016-02-15-detect-document-ready-in-pure-js.md
================================================
---
layout: post
title: Detect document ready in pure JS
tip-number: 46
tip-username: loverajoel
tip-username-profile: https://www.twitter.com/loverajoel
tip-tldr: The cross-browser way to check if the document has loaded in pure JavaScript
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/detect-document-ready-in-pure-js/
categories:
- en
- javascript
---
The cross-browser way to check if the document has loaded in pure JavaScript is using [`readyState`](https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState).
```js
if (document.readyState === 'complete') {
// The page is fully loaded
}
```
You can detect when the document is ready...
```js
let stateCheck = setInterval(() => {
if (document.readyState === 'complete') {
clearInterval(stateCheck);
// document ready
}
}, 100);
```
or with [onreadystatechange](https://developer.mozilla.org/en-US/docs/Web/Events/readystatechange)...
```js
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
// document ready
}
};
```
Use `document.readyState === 'interactive'` to detect when the DOM is ready.
================================================
FILE: _posts/en/javascript/2016-02-16-basics-declarations.md
================================================
---
layout: post
title: Basics declarations
tip-number: 47
tip-username: adaniloff
tip-username-profile: https://github.com/adaniloff
tip-tldr: Understand and work with declarations.
redirect_from:
- /en/basics-declarations/
categories:
- en
- javascript
---
Below, different ways to declare variables in JavaScript.
Comments and console.log should be enough to explain what's happening here:
```js
var y, x = y = 1 //== var x; var y; x = y = 1
console.log('--> 1:', `x = ${x}, y = ${y}`)
// Will print
//--> 1: x = 1, y = 1
```
First, we just set two variables. Nothing much here.
```js
;(() => {
var x = y = 2 // == var x; x = y = 2;
console.log('2.0:', `x = ${x}, y = ${y}`)
})()
console.log('--> 2.1:', `x = ${x}, y = ${y}`)
// Will print
//2.0: x = 2, y = 2
//--> 2.1: x = 1, y = 2
```
As you can see, the code has only changed the global y, as we haven't declared the variable in the closure.
```js
;(() => {
var x, y = 3 // == var x; var y = 3;
console.log('3.0:', `x = ${x}, y = ${y}`)
})()
console.log('--> 3.1:', `x = ${x}, y = ${y}`)
// Will print
//3.0: x = undefined, y = 3
//--> 3.1: x = 1, y = 2
```
Now we declare both variables through var. Meaning they only live in the context of the closure.
```js
;(() => {
var y, x = y = 4 // == var x; var y; x = y = 4
console.log('4.0:', `x = ${x}, y = ${y}`)
})()
console.log('--> 4.1:', `x = ${x}, y = ${y}`)
// Will print
//4.0: x = 4, y = 4
//--> 4.1: x = 1, y = 2
```
Both variables have been declared using var and only after that we've set their values. As local > global, x and y are local in the closure, meaning the global x and y are untouched.
```js
x = 5 // == x = 5
console.log('--> 5:', `x = ${x}, y = ${y}`)
// Will print
//--> 5: x = 5, y = 2
```
This last line is explicit by itself.
You can test this and see the result [thanks to babel](https://babeljs.io/repl/#?experimental=false&evaluate=true&loose=false&spec=false&code=var%20y%2C%20x%20%3D%20y%20%3D%201%20%2F%2F%3D%3D%20var%20x%3B%20var%20y%3B%20x%20%3D%20y%20%3D%201%0Aconsole.log('--%3E%201%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%0A%2F%2F%20Will%20print%0A%2F%2F--%3E%201%3A%20x%20%3D%201%2C%20y%20%3D%201%0A%0A%3B(()%20%3D%3E%20%7B%20%0A%20%20var%20x%20%3D%20y%20%3D%202%20%2F%2F%20%3D%3D%20var%20x%3B%20y%20%3D%202%3B%0A%20%20console.log('2.0%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%7D)()%0Aconsole.log('--%3E%202.1%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%0A%2F%2F%20Will%20print%0A%2F%2F2.0%3A%20x%20%3D%202%2C%20y%20%3D%202%0A%2F%2F--%3E%202.1%3A%20x%20%3D%201%2C%20y%20%3D%202%0A%0A%3B(()%20%3D%3E%20%7B%20%0A%20%20var%20x%2C%20y%20%3D%203%20%2F%2F%20%3D%3D%20var%20x%3B%20var%20y%20%3D%203%3B%0A%20%20console.log('3.0%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%7D)()%0Aconsole.log('--%3E%203.1%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%0A%2F%2F%20Will%20print%0A%2F%2F3.0%3A%20x%20%3D%20undefined%2C%20y%20%3D%203%0A%2F%2F--%3E%203.1%3A%20x%20%3D%201%2C%20y%20%3D%202%0A%0A%3B(()%20%3D%3E%20%7B%20%0A%20%20var%20y%2C%20x%20%3D%20y%20%3D%204%20%2F%2F%20%3D%3D%20var%20x%3B%20var%20y%3B%20x%20%3D%20y%20%3D%203%0A%20%20console.log('4.0%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%7D)()%0Aconsole.log('--%3E%204.1%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%0A%2F%2F%20Will%20print%0A%2F%2F4.0%3A%20x%20%3D%204%2C%20y%20%3D%204%0A%2F%2F--%3E%204.1%3A%20x%20%3D%201%2C%20y%20%3D%202%0A%0Ax%20%3D%205%20%2F%2F%20%3D%3D%20x%20%3D%205%0Aconsole.log('--%3E%205%3A'%2C%20%60x%20%3D%20%24%7Bx%7D%2C%20y%20%3D%20%24%7By%7D%60)%0A%0A%2F%2F%20Will%20print%0A%2F%2F--%3E%205%3A%20x%20%3D%205%2C%20y%20%3D%202).
More informations available on the [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var).
Special thanks to @kurtextrem for his collaboration :)!
================================================
FILE: _posts/en/javascript/2016-02-17-reminders-about-reduce-function-usage.md
================================================
---
layout: post
title: How to `reduce()` arrays
tip-number: 48
tip-username: darul75
tip-username-profile: https://twitter.com/darul75
tip-tldr: Some reminders about using `reduce()`
redirect_from:
- /en/reminders-about-reduce-function-usage/
categories:
- en
- javascript
---
As written in documentation the `reduce()` method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
### Signature
[reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) function accepts 2 parameters (M: mandatory, O: optional):
- (M) a callback **reducer function** to be applied that deals with a pair of previous (result of previous computation) and next element until end of the list.
- (O) an **initial value** to be used as the first argument to the first call of the callback.
So let's see a common usage and later a more sophisticated one.
### Common usage (accumulation, concatenation)
We are on Amazon website (prices in $) and our caddy is quite full, let's compute total.
```javascript
// my current amazon caddy purchases
var items = [{price: 10}, {price: 120}, {price: 1000}];
// our reducer function
var reducer = function add(sumSoFar, item) { return sumSoFar + item.price; };
// do the job
var total = items.reduce(reducer, 0);
console.log(total); // 1130
```
Optional reduce function parameter was primitive integer type 0 in that first case, but it could have been an Object, an Array...instead of a primitive type,
but we will see that later.
Now, cool I received a discount coupon of 20$.
```javascript
var total = items.reduce(reducer,-20);
console.log(total); // 1110
```
### Advanced usage (combination)
This second usage example is inspired by Redux [combineReducers](http://redux.js.org/docs/api/combineReducers.html) function [source](https://github.com/reactjs/redux/blob/master/src/combineReducers.js#L93).
Idea behind is to separate reducer function into separate individual functions and at the end compute a new *single big reducer function*.
To illustrate this, let's create a single object literal with some reducers function able to compute total prices in different currency $, €...
```javascript
var reducers = {
totalInDollar: function(state, item) {
// specific statements...
return state.dollars += item.price;
},
totalInEuros : function(state, item) {
return state.euros += item.price * 0.897424392;
},
totalInPounds : function(state, item) {
return state.pounds += item.price * 0.692688671;
},
totalInYen : function(state, item) {
return state.yens += item.price * 113.852;
}
// more...
};
```
Then, we create a new swiss knife function
- responsible for applying each partial reduce functions.
- that will return a new callback reducer function
```javascript
var combineTotalPriceReducers = function(reducers) {
return function(state, item) {
return Object.keys(reducers).reduce(
function(nextState, key) {
reducers[key](state, item);
return state;
},
{}
);
}
};
```
Now let's see how using it.
```javascript
var bigTotalPriceReducer = combineTotalPriceReducers(reducers);
var initialState = {dollars: 0, euros:0, yens: 0, pounds: 0};
var totals = items.reduce(bigTotalPriceReducer, initialState);
console.log(totals);
/*
Object {dollars: 1130, euros: 1015.11531904, yens: 127524.24, pounds: 785.81131152}
*/
```
I hope this approach can give you another idea of using reduce() function for your own needs.
Your reduce function could handle an history of each computation by instance as it is done in Ramdajs with [scan](http://ramdajs.com/docs/#scan) function
[JSFiddle to play with](https://jsfiddle.net/darul75/81tgt0cd/)
================================================
FILE: _posts/en/javascript/2016-02-26-extract-unix-timestamp-easily.md
================================================
---
layout: post
title: Easiest way to extract unix timestamp in JS
tip-number: 49
tip-username: nmrony
tip-username-profile: https://github.com/nmrony
tip-tldr: In Javascript you can easily get the unix timestamp
redirect_from:
- /en/extract-unix-timestamp-easily/
categories:
- en
- javascript
---
We frequently need to calculate with unix timestamp. There are several ways to grab the timestamp. For current unix timestamp easiest and fastest way is
```js
const dateTime = Date.now();
const timestamp = Math.floor(dateTime / 1000);
```
or
```js
const dateTime = new Date().getTime();
const timestamp = Math.floor(dateTime / 1000);
```
To get unix timestamp of a specific date pass `YYYY-MM-DD` or `YYYY-MM-DDT00:00:00Z` as parameter of `Date` constructor. For example
```js
const dateTime = new Date('2012-06-08').getTime();
const timestamp = Math.floor(dateTime / 1000);
```
You can just add a `+` sign also when declaring a `Date` object like below
```js
const dateTime = +new Date();
const timestamp = Math.floor(dateTime / 1000);
```
or for specific date
```js
const dateTime = +new Date('2012-06-08');
const timestamp = Math.floor(dateTime / 1000);
```
Under the hood the runtime calls `valueOf` method of the `Date` object. Then the unary `+` operator calls `toNumber()` with that returned value. For detailed explanation please check the following links
* [Date.prototype.valueOf](http://es5.github.io/#x15.9.5.8)
* [Unary + operator](http://es5.github.io/#x11.4.6)
* [toNumber()](http://es5.github.io/#x9.3)
* [Date Javascript MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
* [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse)
================================================
FILE: _posts/en/javascript/2016-03-03-helpful-console-log-hacks.md
================================================
---
layout: post
title: Helpful Console Logging Tricks
tip-number: 50
tip-username: zackhall
tip-username-profile: https://twitter.com/zthall
tip-tldr: Helpful logging techniques using coercion and conditonal breakpoints.
redirect_from:
- /en/helpful-console-log-hacks/
categories:
- en
- javascript
---
## Using conditional breakpoints to log data
If you wanted to log to the console a value each time a function is called, you can use conditional break points to do this. Open up your dev tools, find the function where you'd like to log data to the console and set a breakpoint with the following condition:
```js
console.log(data.value) && false
```
A conditional breakpoint pauses the page thread only if the condition for the breakpoint evaluates to true. So by using a condition like console.log('foo') && false it's guaranteed to evaluate to false since you're putting the literal false in the AND condition. So this will not pause the page thread when it's hit, but it will log data to the console. This can also be used to count how many times a function or callback is called.
Here's how you can set a conditional breakpoint in [Edge](https://dev.windows.com/en-us/microsoft-edge/platform/documentation/f12-devtools-guide/debugger/#setting-and-managing-breakpoints "Managing Breakpoints in Edge"), [Chrome](https://developer.chrome.com/devtools/docs/javascript-debugging#breakpoints "Managing Breakpoints in Chrome"), [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Set_a_conditional_breakpoint "Managing Breakpoints in Firefox") and [Safari](https://developer.apple.com/library/mac/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/Debugger/Debugger.html "Managing Breakpoints in Safari").
## Printing a function variable to console
Have you ever logged a function variable to the console and weren't able to just view the function's code? The quickest way to see the function's code is to coerce it to a string using concatenation with an empty string.
```js
console.log(funcVariable + '');
```
================================================
FILE: _posts/en/javascript/2016-03-16-DOM-event-listening-made-easy.md
================================================
---
layout: post
title: DOM event listening made easy
tip-number: 51
tip-username: octopitus
tip-username-profile: https://github.com/octopitus
tip-tldr: An elegant and easy way to handle DOM events
redirect_from:
- /en/DOM-event-listening-made-easy/
categories:
- en
- javascript
---
Many of us are still doing these things:
- `element.addEventListener('type', obj.method.bind(obj))`
- `element.addEventListener('type', function (event) {})`
- `element.addEventListener('type', (event) => {})`
The above examples all create new anonymous event handlers that can't be removed when no longer needed. This may cause performance problems or unexpected logic bugs, when handlers that you no longer need still get accidentally triggered through unexpected user interactions or [event bubbling](http://www.javascripter.net/faq/eventbubbling.htm).
Safer event-handling patterns include the following:
Use a reference:
```js
const handler = function () {
console.log("Tada!")
}
element.addEventListener("click", handler)
// Later on
element.removeEventListener("click", handler)
```
Named function that removes itself:
```js
element.addEventListener('click', function click(e) {
if (someCondition) {
return e.currentTarget.removeEventListener('click', click);
}
});
```
A better approach:
```js
function handleEvent (eventName, {onElement, withCallback, useCapture = false} = {}, thisArg) {
const element = onElement || document.documentElement
function handler (event) {
if (typeof withCallback === 'function') {
withCallback.call(thisArg, event)
}
}
handler.destroy = function () {
return element.removeEventListener(eventName, handler, useCapture)
}
element.addEventListener(eventName, handler, useCapture)
return handler
}
// Anytime you need
const handleClick = handleEvent('click', {
onElement: element,
withCallback: (event) => {
console.log('Tada!')
}
})
// And anytime you want to remove it
handleClick.destroy()
```
================================================
FILE: _posts/en/javascript/2016-04-05-return-values-with-the-new-operator.md
================================================
---
layout: post
title: Return Values with the 'new' Operator
tip-number: 52
tip-username: Morklympious
tip-username-profile: https://github.com/morklympious
tip-tldr: Understand what gets returned when using new vs. not using new.
redirect_from:
- /en/return-values-with-the-new-operator/
categories:
- en
- javascript
---
You're going to run into some instances where you'll be using `new` to allocate new objects in JavaScript. It's going to blow your mind unless you read this tip to understand what's happening behind the scenes.
The `new` operator in JavaScript is an operator that, under reasonable circumstances, returns a new instance of an object. Let's say we have a constructor function:
````js
function Thing() {
this.one = 1;
this.two = 2;
}
var myThing = new Thing();
myThing.one // 1
myThing.two // 2
````
__Note__: `this` refers to the new object created by `new`. Otherwise if `Thing()` is called without `new`, __no object is created__, and `this` is going to point to the global object, which is `window`. This means that:
1. You'll suddenly have two new global variables named `one` and `two`.
2. `myThing` is now undefined, since nothing is returned in `Thing()`.
Now that you get that example, here's where things get a little bit wonky. Let's say I add something to the constructor function, a little SPICE:
````js
function Thing() {
this.one = 1;
this.two = 2;
return 5;
}
var myThing = new Thing();
````
Now, what does myThing equal? Is it 5? is it an object? Is it my crippled sense of self-worth? The world may never know!
Except the world does know:
````js
myThing.one // 1
myThing.two // 2
````
Interestingly enough, we never actually see the five that we supposedly 'returned' from our constructor. That's weird, isn't it? What are you doing function? WHERE'S THE FIVE? Let's try it with something else.
Let's return a non-primitive type instead, something like an object.
````js
function Thing() {
this.one = 1;
this.two = 2;
return {
three: 3,
four: 4
};
}
var myThing = new Thing();
````
Let's check it out. A quick console.log reveals all:
````js
console.log(myThing);
/*
Object {three: 3, four: 4}
What happened to this.one and this.two!?
They've been stomped, my friend.
*/
````
__Here's where we learn:__ When you invoke a function with the `new` keyword, you can set properties on it using the keyword `this` (but you probably already knew that). Returning a primitive value from a function you called with the `new` keyword will not return the value you specified, but instead will return the `this` instance of the function (the one you put properties on, like `this.one = 1;`).
However, returning a non-primitive, like an `object`, `array`, or `function` will stomp on the `this` instance, and return that non-primitive instead, effectively ruining all the hard work you did assigning everything to `this`.
================================================
FILE: _posts/en/javascript/2016-04-21-get-file-extension.md
================================================
---
layout: post
title: Get File Extension
tip-number: 53
tip-username: richzw
tip-username-profile: https://github.com/richzw
tip-tldr: How to get the file extension more efficiently?
redirect_from:
- /en/get-file-extension/
categories:
- en
- javascript
---
### Question: How to get the file extension?
```javascript
var file1 = "50.xsl";
var file2 = "30.doc";
getFileExtension(file1); //returs xsl
getFileExtension(file2); //returs doc
function getFileExtension(filename) {
/*TODO*/
}
```
### Solution 1: Regular Expression
```js
function getFileExtension1(filename) {
return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename)[0] : undefined;
}
```
### Solution 2: String `split` method
```js
function getFileExtension2(filename) {
return filename.split('.').pop();
}
```
Those two solutions couldnot handle some edge cases, here is another more robust solution.
### Solution3: String `slice`, `lastIndexOf` methods
```js
function getFileExtension3(filename) {
return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
}
console.log(getFileExtension3('')); // ''
console.log(getFileExtension3('filename')); // ''
console.log(getFileExtension3('filename.txt')); // 'txt'
console.log(getFileExtension3('.hiddenfile')); // ''
console.log(getFileExtension3('filename.with.many.dots.ext')); // 'ext'
```
_How does it works?_
- [String.lastIndexOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf) method returns the last occurrence of the specified value (`'.'` in this case). Returns `-1` if the value is not found.
- The return values of `lastIndexOf` for parameter `'filename'` and `'.hiddenfile'` are `-1` and `0` respectively. [Zero-fill right shift operator (>>>)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#%3E%3E%3E_%28Zero-fill_right_shift%29) will transform `-1` to `4294967295` and `-2` to `4294967294`, here is one trick to insure the filename unchanged in those edge cases.
- [String.prototype.slice()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) extracts file extension from the index that was calculated above. If the index is more than the length of the filename, the result is `""`.
### Comparison
| Solution | Paramters | Results |
| ----------------------------------------- |:-------------------:|:--------:|
| Solution 1: Regular Expression | ''<br> 'filename' <br> 'filename.txt' <br> '.hiddenfile' <br> 'filename.with.many.dots.ext' | undefined <br> undefined <br> 'txt' <br> 'hiddenfile' <br> 'ext' <br> |
| Solution 2: String `split` | ''<br> 'filename' <br> 'filename.txt' <br> '.hiddenfile' <br> 'filename.with.many.dots.ext' | '' <br> 'filename' <br> 'txt' <br> 'hiddenfile' <br> 'ext' <br> |
| Solution 3: String `slice`, `lastIndexOf` | ''<br> 'filename' <br> 'filename.txt' <br> '.hiddenfile' <br> 'filename.with.many.dots.ext' | '' <br> '' <br> 'txt' <br> '' <br> 'ext' <br> |
### Live Demo and Performance
[Here](https://jsbin.com/tipofu/edit?js,console) is the live demo of the above codes.
[Here](http://jsperf.com/extract-file-extension) is the performance test of those 3 solutions.
### Source
[How can I get file extensions with JavaScript](http://stackoverflow.com/questions/190852/how-can-i-get-file-extensions-with-javascript)
================================================
FILE: _posts/en/javascript/2016-05-06-use-optional-arguments.md
================================================
---
layout: post
title: How to use optional arguments in functions (with optional callback)
tip-number: 54
tip-username: alphashuro
tip-username-profile: https://github.com/alphashuro
tip-tldr: You can make function arguments and callback optional
redirect_from:
- /en/use-optional-arguments/
categories:
- en
- javascript
---
Example function where arguments 2 and 3 are optional
```javascript
function example( err, optionalA, optionalB, callback ) {
// retrieve arguments as array
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
};
// first argument is the error object
// shift() removes the first item from the
// array and returns it
err = args.shift();
// if last argument is a function then its the callback function.
// pop() removes the last item in the array
// and returns it
if (typeof args[args.length-1] === 'function') {
callback = args.pop();
}
// if args still holds items, these are
// your optional items which you could
// retrieve one by one like this:
if (args.length > 0) optionalA = args.shift(); else optionalA = null;
if (args.length > 0) optionalB = args.shift(); else optionalB = null;
// continue as usual: check for errors
if (err) {
return callback && callback(err);
}
// for tutorial purposes, log the optional parameters
console.log('optionalA:', optionalA);
console.log('optionalB:', optionalB);
console.log('callback:', callback);
/* do your thing */
}
// ES6 with shorter, more terse code
function example(...args) {
// first argument is the error object
const err = args.shift();
// if last argument is a function then its the callback function
const callback = (typeof args[args.length-1] === 'function') ? args.pop() : null;
// if args still holds items, these are your optional items which you could retrieve one by one like this:
const optionalA = (args.length > 0) ? args.shift() : null;
const optionalB = (args.length > 0) ? args.shift() : null;
// ... repeat for more items
if (err && callback) return callback(err);
/* do your thing */
}
// invoke example function with and without optional arguments
example(null, 'AA');
example(null, function (err) { /* do something */ });
example(null, 'AA', function (err) {});
example(null, 'AAAA', 'BBBB', function (err) {});
```
### How do you determine if optionalA or optionalB is intended?
Design your function to require optionalA in order to accept optionalB
================================================
FILE: _posts/en/javascript/2016-05-12-make-easy-loop-on-array.md
================================================
---
layout: post
title: Create an easy loop using an array
tip-number: 55
tip-username: jamet-julien
tip-username-profile: https://github.com/jamet-julien
tip-tldr: Sometimes, we need to loop endlessly over an array of items, like a carousel of images or an audio playlist. Here’s how to take an array and give it “looping powers”
redirect_from:
- /en/make-easy-loop-on-array/
categories:
- en
- javascript
---
Sometimes, we need to loop endlessly over an array of items, like a carousel of images or an audio playlist. Here's how to take an array and give it "looping powers":
```js
var aList = ['A','B','C','D','E'];
function make_looper( arr ){
arr.loop_idx = 0;
// return current item
arr.current = function(){
if( this.loop_idx < 0 ){// First verification
this.loop_idx = this.length - 1;// update loop_idx
}
if( this.loop_idx >= this.length ){// second verification
this.loop_idx = 0;// update loop_idx
}
return arr[ this.loop_idx ];//return item
};
// increment loop_idx AND return new current
arr.next = function(){
this.loop_idx++;
return this.current();
};
// decrement loop_idx AND return new current
arr.prev = function(){
this.loop_idx--;
return this.current();
};
}
make_looper( aList);
aList.current();// -> A
aList.next();// -> B
aList.next();// -> C
aList.next();// -> D
aList.next();// -> E
aList.next();// -> A
aList.pop() ;// -> E
aList.prev();// -> D
aList.prev();// -> C
aList.prev();// -> B
aList.prev();// -> A
aList.prev();// -> D
```
Using the ```%``` ( Modulus ) operator is prettier.The modulus return division's rest ( ``` 2 % 5 = 1``` and ``` 5 % 5 = 0```):
```js
var aList = ['A','B','C','D','E'];
function make_looper( arr ){
arr.loop_idx = 0;
// return current item
arr.current = function(){
this.loop_idx = ( this.loop_idx ) % this.length;// no verification !!
return arr[ this.loop_idx ];
};
// increment loop_idx AND return new current
arr.next = function(){
this.loop_idx++;
return this.current();
};
// decrement loop_idx AND return new current
arr.prev = function(){
this.loop_idx += this.length - 1;
return this.current();
};
}
make_looper( aList);
aList.current();// -> A
aList.next();// -> B
aList.next();// -> C
aList.next();// -> D
aList.next();// -> E
aList.next();// -> A
aList.pop() ;// -> E
aList.prev();// -> D
aList.prev();// -> C
aList.prev();// -> B
aList.prev();// -> A
aList.prev();// -> D
```
================================================
FILE: _posts/en/javascript/2016-08-02-copy-to-clipboard.md
================================================
---
layout: post
title: Copy to Clipboard
tip-number: 56
tip-username: loverajoel
tip-username-profile: https://twitter.com/loverajoel
tip-tldr: This week I had to create a common "Copy to Clipboard" button, I've never created one before and I want to share how I made it.
tip-writer-support: https://www.coinbase.com/loverajoel
redirect_from:
- /en/copy-to-clipboard/
categories:
- en
- javascript
---
This is a simple tip, this week I had to create a common "Copy to Clipboard" button, I've never created one before and I want to share how I made it.
It's easy, the bad thing is that we must add an `<input/>` with the text to be copied to the DOM. Then, we selected the content and execute the copy command with [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand).
`execCommand('copy')` will copy the actual selected content.
Also, this command that now is [supported](http://caniuse.com/#search=execCommand) by all the latest version of browsers, allows us to execute another system commands like `copy`, `cut`, `paste`, and make changes like fonts color, size, and much more.
```js
document.querySelector('#input').select();
document.execCommand('copy');
```
##### Playground
<div>
<a class="jsbin-embed" href="http://jsbin.com/huhozu/embed?js,output">JS Bin on jsbin.com</a><script src="http://static.jsbin.com/js/embed.min.js?3.39.11"></script>
</div>
================================================
FILE: _posts/en/javascript/2016-08-10-comma-operaton-in-js.md
================================================
---
layout: post
title: Comma operator in JS
tip-number: 57
tip-username: bhaskarmelkani
tip-username-profile: https://www.twitter.com/bhaskarmelkani
tip-tldr: When placed in an expression, it evaluates every expression from left to right and returns the last one.
redirect_from:
- /en/comma-operaton-in-js/
categories:
- en
- javascript
---
Apart from being just a delimiter, the comma operator allows you to put multiple statements in a place where one statement is expected.
Eg:-
```js
for(var i=0, j=0; i<5; i++, j++, j++){
console.log("i:"+i+", j:"+j);
}
```
Output:-
```js
i:0, j:0
i:1, j:2
i:2, j:4
i:3, j:6
i:4, j:8
```
When placed in an expression, it evaluates every expression from left to right and returns the right most expression.
Eg:-
```js
function a(){console.log('a'); return 'a';}
function b(){console.log('b'); return 'b';}
function c(){console.log('c'); return 'c';}
var x = (a(), b(), c());
console.log(x); // Outputs "c"
```
Output:-
```js
"a"
"b"
"c"
"c"
```
* Note: The comma(`,`) operator has the lowest priority of all javascript operators, so without the parenthesis the expression would become: `(x = a()), b(), c();`.
##### Playground
<div>
<a class="jsbin-embed" href="http://jsbin.com/vimogap/embed?js,console">JS Bin on jsbin.com</a><script src="http://static.jsbin.com/js/embed.min.js?3.39.11"></script>
</div>
================================================
FILE: _posts/en/javascript/2016-08-17-break-continue-loop-functional.md
================================================
---
layout: post
title: Breaking or continuing loop in functional programming
tip-number: 58
tip-username: vamshisuram
tip-username-profile: https://github.com/vamshisuram
tip-tldr: A common task for us is iterate over a list looking for a value or values, but we can't return from inside a loop so we will have to iterate the whole array, even if the item we search is the first in the list, in this tip we will see how to short circuit with `.some` and `.every`.
redirect_from:
- /en/break-continue-loop-functional/
categories:
- en
- javascript
---
A common requirement of iteration is cancelation. Using `for` loops we can `break` to end iteration early.
```javascript
const a = [0, 1, 2, 3, 4];
for (var i = 0; i < a.length; i++) {
if (a[i] === 2) {
break; // stop the loop
}
console.log(a[i]);
}
//> 0, 1
```
Another common requirement is to close over our variables.
A quick approach is to use `.forEach` but
then we lack the ability to `break`. In this situation the closest we get is `continue` functionality through `return`.
```javascript
[0, 1, 2, 3, 4].forEach(function(val, i) {
if (val === 2) {
// how do we stop?
return true;
}
console.log(val); // your code
});
//> 0, 1, 3, 4
```
The `.some` is a method on Array prototype. It tests whether some element in the array passes the test implemented by the provided function. If any value is returning true, then it stops executing. Here is a [MDN link](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some) for more details.
An example quoted from that link
```javascript
const isBiggerThan10 = numb => numb > 10;
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
```
Using `.some` we get iteration functionally similar to `.forEach` but with the ability to `break` through `return` instead.
```javascript
[0, 1, 2, 3, 4].some(function(val, i) {
if (val === 2) {
return true;
}
console.log(val); // your code
});
//> 0, 1
```
You keep returning `false` to make it `continue` to n
gitextract_f1dq9svt/
├── CONTRIBUTING.md
├── CONTRIBUTING_es_ES.md
├── CONTRIBUTING_zh_CN.md
├── CONTRIBUTING_zh_TW.md
├── LICENSE.md
├── POST_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
├── README.md
└── _posts/
├── en/
│ ├── angular/
│ │ ├── 2016-01-01-angularjs-digest-vs-apply.md
│ │ └── 2017-03-07-preventing-unwanted-scopes-creation-in-angularjs.md
│ ├── javascript/
│ │ ├── 2015-12-29-insert-item-inside-an-array.md
│ │ ├── 2016-01-03-improve-nested-conditionals.md
│ │ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ │ ├── 2016-01-05-differences-between-undefined-and-null.md
│ │ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ │ ├── 2016-01-07-use-strict-and-get-lazy.md
│ │ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ │ ├── 2016-01-09-template-strings.md
│ │ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ │ ├── 2016-01-11-hoisting.md
│ │ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ │ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ │ ├── 2016-01-14-fat-arrow-functions.md
│ │ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ │ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ │ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ │ ├── 2016-01-18-rounding-the-fast-way.md
│ │ ├── 2016-01-19-safe-string-concatenation.md
│ │ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ │ ├── 2016-01-21-shuffle-an-array.md
│ │ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ │ ├── 2016-01-23-converting-to-number-fast-way.md
│ │ ├── 2016-01-24-use_===_instead_of_==.md
│ │ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ │ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ │ ├── 2016-01-27-short-circuit-evaluation-in-js.md
│ │ ├── 2016-01-28-curry-vs-partial-application.md
│ │ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ │ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ │ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ │ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ │ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ │ ├── 2016-02-03-implementing-asynchronous-loops.md
│ │ ├── 2016-02-04-assignment-shorthands.md
│ │ ├── 2016-02-05-observe-dom-changes.md
│ │ ├── 2016-02-06-deduplicate-an-array.md
│ │ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ │ ├── 2016-02-08-advanced-properties.md
│ │ ├── 2016-02-09-using-json-stringify.md
│ │ ├── 2016-02-10-array-average-and-median.md
│ │ ├── 2016-02-11-preventing-unapply-attacks.md
│ │ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ │ ├── 2016-02-13-know-the-passing-mechanism.md
│ │ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ │ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ │ ├── 2016-02-16-basics-declarations.md
│ │ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ │ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ │ ├── 2016-03-03-helpful-console-log-hacks.md
│ │ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ │ ├── 2016-04-05-return-values-with-the-new-operator.md
│ │ ├── 2016-04-21-get-file-extension.md
│ │ ├── 2016-05-06-use-optional-arguments.md
│ │ ├── 2016-05-12-make-easy-loop-on-array.md
│ │ ├── 2016-08-02-copy-to-clipboard.md
│ │ ├── 2016-08-10-comma-operaton-in-js.md
│ │ ├── 2016-08-17-break-continue-loop-functional.md
│ │ ├── 2016-08-25-keyword-var-vs-let.md
│ │ ├── 2016-10-28-three-useful-hacks.md
│ │ ├── 2017-01-19-binding-objects-to-functions.md
│ │ ├── 2017-03-09-working-with-websocket-timeout.md
│ │ ├── 2017-03-12-3-array-hacks.md
│ │ ├── 2017-03-16-tapping-for-quick-debugging.md
│ │ ├── 2017-03-29-recursion-iteration-and-tail-calls-in-js.md
│ │ ├── 2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md
│ │ ├── 2017-04-05-picking-and-rejecting-object-properties.md
│ │ ├── 2017-04-11-protocols-for-the-brave.md
│ │ ├── 2017-04-24-improving-your-async-functions-with-webworkers.md
│ │ ├── 2017-06-14-closures-inside-loops.md
│ │ ├── 2017-06-14-immutable-structures-and-cloning.md
│ │ ├── 2017-06-15-looping-over-arrays.md
│ │ ├── 2017-09-01-hash-maps-without-side-effects.md
│ │ ├── 2018-11-25-creating-immutable-objects-in-native-javascript.md
│ │ ├── 2020-10-13-what-is-a-functional-inheritance.md
│ │ ├── 2020-10-15-what-is-a-currying-function.md
│ │ ├── 2020-10-20-what-is-the-temporal-dead-zone.md
│ │ ├── 2020-10-22-difference-between-target-and-currentTarget.md
│ │ ├── 2020-10-27-what-is-a-spread-operator.md
│ │ ├── 2020-11-04-what-is-a-void-operator.md
│ │ ├── 2020-11-17-what-is-the-promise-executor.md
│ │ └── 2021-02-02-what-is-the-javascript-ternary-operator.md
│ ├── more/
│ │ └── 2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md
│ └── react/
│ ├── 2016-01-02-keys-in-children-components-are-important.md
│ ├── 2017-03-27-state-to-props-maps-with-memory.md
│ ├── 2017-04-04-enhancing-react-components-composition.md
│ ├── 2017-04-10-adventurers-guide-to-react.md
│ ├── 2017-05-29-upping-performance-by-appending-keying.md
│ └── 2021-07-18-trace-the-reason-make-your-page-rerender.md
├── es_ES/
│ ├── angular/
│ │ └── 2016-01-01-angularjs-digest-vs-apply.md
│ ├── javascript/
│ │ ├── 2015-12-29-insert-item-inside-an-array.md
│ │ ├── 2016-01-03-improve-nested-conditionals.md
│ │ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ │ ├── 2016-01-05-differences-between-undefined-and-null.md
│ │ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ │ ├── 2016-01-07-use-strict-and-get-lazy.md
│ │ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ │ ├── 2016-01-09-template-strings.md
│ │ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ │ ├── 2016-01-11-hoisting.md
│ │ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ │ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ │ ├── 2016-01-14-fat-arrow-functions.md
│ │ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ │ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ │ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ │ ├── 2016-01-18-rounding-the-fast-way.md
│ │ ├── 2016-01-19-safe-string-concatenation.md
│ │ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ │ ├── 2016-01-21-shuffle-an-array.md
│ │ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ │ ├── 2016-01-23-converting-to-number-fast-way.md
│ │ ├── 2016-01-24-use_===_instead_of_==.md
│ │ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ │ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ │ ├── 2016-01-27-short-circiut-evaluation-in-js.md
│ │ ├── 2016-01-28-curry-vs-partial-application.md
│ │ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ │ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ │ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ │ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ │ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ │ ├── 2016-02-03-implementing-asynchronous-loops.md
│ │ ├── 2016-02-04-assignment-shorthands.md
│ │ ├── 2016-02-05-observe-dom-changes.md
│ │ ├── 2016-02-06-deduplicate-an-array.md
│ │ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ │ ├── 2016-02-08-advanced-properties.md
│ │ ├── 2016-02-09-using-json-stringify.md
│ │ ├── 2016-02-10-array-average-and-median.md
│ │ ├── 2016-02-11-preventing-unapply-attacks.md
│ │ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ │ ├── 2016-02-13-know-the-passing-mechanism.md
│ │ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ │ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ │ ├── 2016-02-16-basics-declarations.md
│ │ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ │ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ │ ├── 2016-03-03-helpful-console-log-hacks.md
│ │ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ │ ├── 2016-04-05-return-values-with-the-new-operator.md
│ │ ├── 2016-04-21-get-file-extension.md
│ │ ├── 2016-05-06-use-optional-arguments.md
│ │ └── 2016-05-12-make-easy-loop-on-array.md
│ └── react/
│ └── 2016-01-02-keys-in-children-components-are-important.md
├── zh_CN/
│ ├── angular/
│ │ └── 2016-01-01-angularjs-digest-vs-apply.md
│ ├── javascript/
│ │ ├── 2015-12-29-insert-item-inside-an-array.md
│ │ ├── 2016-01-03-improve-nested-conditionals.md
│ │ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ │ ├── 2016-01-05-differences-between-undefined-and-null.md
│ │ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ │ ├── 2016-01-07-use-strict-and-get-lazy.md
│ │ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ │ ├── 2016-01-09-template-strings.md
│ │ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ │ ├── 2016-01-11-hoisting.md
│ │ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ │ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ │ ├── 2016-01-14-fat-arrow-functions.md
│ │ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ │ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ │ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ │ ├── 2016-01-18-rounding-the-fast-way.md
│ │ ├── 2016-01-19-safe-string-concatenation.md
│ │ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ │ ├── 2016-01-21-shuffle-an-array.md
│ │ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ │ ├── 2016-01-23-converting-to-number-fast-way.md
│ │ ├── 2016-01-24-use_===_instead_of_==.md
│ │ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ │ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ │ ├── 2016-01-27-short-circuit-evaluation-in-js.md
│ │ ├── 2016-01-28-curry-vs-partial-application.md
│ │ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ │ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ │ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ │ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ │ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ │ ├── 2016-02-03-implementing-asynchronous-loops.md
│ │ ├── 2016-02-04-assignment-shorthands.md
│ │ ├── 2016-02-05-observe-dom-changes.md
│ │ ├── 2016-02-06-deduplicate-an-array.md
│ │ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ │ ├── 2016-02-08-advanced-properties.md
│ │ ├── 2016-02-09-using-json-stringify.md
│ │ ├── 2016-02-10-array-average-and-median.md
│ │ ├── 2016-02-11-preventing-unapply-attacks.md
│ │ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ │ ├── 2016-02-13-know-the-passing-mechanism.md
│ │ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ │ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ │ ├── 2016-02-16-basics-declarations.md
│ │ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ │ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ │ ├── 2016-03-03-helpful-console-log-hacks.md
│ │ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ │ ├── 2016-04-05-return-values-with-the-new-operator.md
│ │ ├── 2016-04-21-get-file-extension.md
│ │ ├── 2016-05-06-use-optional-arguments.md
│ │ ├── 2016-05-12-make-easy-loop-on-array.md
│ │ ├── 2016-08-02-copy-to-clipboard.md
│ │ ├── 2016-08-10-comma-operaton-in-js.md
│ │ ├── 2016-08-17-break-continue-loop-functional.md
│ │ ├── 2016-08-25-keyword-var-vs-let.md
│ │ ├── 2016-10-28-three-useful-hacks.md
│ │ ├── 2017-01-19-binding-objects-to-functions.md
│ │ ├── 2017-03-09-working-with-websocket-timeout.md
│ │ ├── 2017-03-12-3-array-hacks.md
│ │ ├── 2017-03-16-tapping-for-quick-debugging.md
│ │ ├── 2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md
│ │ └── 2017-04-05-picking-and-rejecting-object-properties.md
│ ├── more/
│ │ └── 2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md
│ └── react/
│ └── 2016-01-02-keys-in-children-components-are-important.md
└── zh_TW/
├── angular/
│ ├── 2016-01-01-angularjs-digest-vs-apply.md
│ └── 2017-03-07-preventing-unwanted-scopes-creation-in-angularjs.md
├── javascript/
│ ├── 2015-12-29-insert-item-inside-an-array.md
│ ├── 2016-01-03-improve-nested-conditionals.md
│ ├── 2016-01-04-sorting-strings-with-accented-characters.md
│ ├── 2016-01-05-differences-between-undefined-and-null.md
│ ├── 2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md
│ ├── 2016-01-07-use-strict-and-get-lazy.md
│ ├── 2016-01-08-converting-a-node-list-to-an-array.md
│ ├── 2016-01-09-template-strings.md
│ ├── 2016-01-10-check-if-a-property-is-in-a-object.md
│ ├── 2016-01-11-hoisting.md
│ ├── 2016-01-12-pseudomandatory-parameters-in-es6-functions.md
│ ├── 2016-01-13-tip-to-measure-performance-of-a-javascript-block.md
│ ├── 2016-01-14-fat-arrow-functions.md
│ ├── 2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md
│ ├── 2016-01-16-passing-arguments-to-callback-functions.md
│ ├── 2016-01-17-nodejs-run-a-module-if-it-is-not-required.md
│ ├── 2016-01-18-rounding-the-fast-way.md
│ ├── 2016-01-19-safe-string-concatenation.md
│ ├── 2016-01-20-return-objects-to-enable-chaining-of-functions.md
│ ├── 2016-01-21-shuffle-an-array.md
│ ├── 2016-01-22-two-ways-to-empty-an-array.md
│ ├── 2016-01-23-converting-to-number-fast-way.md
│ ├── 2016-01-24-use_===_instead_of_==.md
│ ├── 2016-01-25-Using-immediately-invoked-function-expression.md
│ ├── 2016-01-26-filtering-and-sorting-a-list-of-strings.md
│ ├── 2016-01-27-short-circiut-evaluation-in-js.md
│ ├── 2016-01-28-curry-vs-partial-application.md
│ ├── 2016-01-29-speed-up-recursive-functions-with-memoization.md
│ ├── 2016-01-30-converting-truthy-falsy-values-to-boolean.md
│ ├── 2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md
│ ├── 2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md
│ ├── 2016-02-02-create-range-0-n-easily-using-one-line.md
│ ├── 2016-02-03-implementing-asynchronous-loops.md
│ ├── 2016-02-04-assignment-shorthands.md
│ ├── 2016-02-05-observe-dom-changes.md
│ ├── 2016-02-06-deduplicate-an-array.md
│ ├── 2016-02-07-flattening-multidimensional-arrays-in-javascript.md
│ ├── 2016-02-08-advanced-properties.md
│ ├── 2016-02-09-using-json-stringify.md
│ ├── 2016-02-10-array-average-and-median.md
│ ├── 2016-02-11-preventing-unapply-attacks.md
│ ├── 2016-02-12-use-destructuring-in-function-parameters.md
│ ├── 2016-02-13-know-the-passing-mechanism.md
│ ├── 2016-02-14-calculate-the-max-min-value-from-an-array.md
│ ├── 2016-02-15-detect-document-ready-in-pure-js.md
│ ├── 2016-02-16-basics-declarations.md
│ ├── 2016-02-17-reminders-about-reduce-function-usage.md
│ ├── 2016-02-26-extract-unix-timestamp-easily.md
│ ├── 2016-03-03-helpful-console-log-hacks.md
│ ├── 2016-03-16-DOM-event-listening-made-easy.md
│ ├── 2016-04-05-return-values-with-the-new-operator.md
│ ├── 2016-04-21-get-file-extension.md
│ ├── 2016-05-06-use-optional-arguments.md
│ ├── 2016-05-12-make-easy-loop-on-array.md
│ ├── 2016-08-02-copy-to-clipboard.md
│ ├── 2016-08-10-comma-operaton-in-js.md
│ ├── 2016-08-17-break-continue-loop-functional.md
│ ├── 2016-08-25-keyword-var-vs-let.md
│ ├── 2016-10-28-three-useful-hacks.md
│ ├── 2017-01-19-binding-objects-to-functions.md
│ ├── 2017-03-09-working-with-websocket-timeout.md
│ ├── 2017-03-12-3-array-hacks.md
│ ├── 2017-03-16-tapping-for-quick-debugging.md
│ ├── 2017-03-29-recursion-iteration-and-tail-calls-in-js.md
│ ├── 2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md
│ ├── 2017-04-05-picking-and-rejecting-object-properties.md
│ └── 2017-06-15-looping-over-arrays.md
├── more/
│ └── 2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md
└── react/
├── 2016-01-02-keys-in-children-components-are-important.md
├── 2017-03-27-state-to-props-maps-with-memory.md
├── 2017-04-04-enhancing-react-components-composition.md
└── 2017-04-10-adventurers-guide-to-react.md
Condensed preview — 296 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (669K chars).
[
{
"path": "CONTRIBUTING.md",
"chars": 1617,
"preview": "# How to submit your tip\n\nTo submit a tip to the list, fork the repository and add your tip in a new file in the correct"
},
{
"path": "CONTRIBUTING_es_ES.md",
"chars": 1577,
"preview": "# Como enviar tu tip\n\nPara agregar tu tip a la lista, debes forkear el repositorio y agregar tu tip en un nuevo archivos"
},
{
"path": "CONTRIBUTING_zh_CN.md",
"chars": 850,
"preview": "# 如何提交小知识\n\n将小知识提交到本列表,`fork`此仓库(repository)然后将的小知识放到对应文件夹(根据语言)的新文件中。新文件的名字应该像`2016-xx-xx-name-of-your-tip`这样。\n\n书写小知识时请按"
},
{
"path": "CONTRIBUTING_zh_TW.md",
"chars": 814,
"preview": "# 如何提交你的 tip\n\n如果要提交 tip 到目錄,fork 這個儲存庫(repository)並加入你的 tip 到檔案內,放入到正確的資料夾(根據語系)。檔案名稱應該為 `2016-xx-xx-name-of-your-tip`。\n"
},
{
"path": "LICENSE.md",
"chars": 35140,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "POST_TEMPLATE.md",
"chars": 311,
"preview": "---\nlayout: *post\n\ntitle: Demo post\ntip-number: xx\ntip-username: tip_js\ntip-username-profile: https://twitter.com/tips_j"
},
{
"path": "PULL_REQUEST_TEMPLATE.md",
"chars": 166,
"preview": "## [Title here]\n## TL;DR;\n[content here]\n## Username\n[twitter account link or github account link ej: [@tips-js](https:/"
},
{
"path": "README.md",
"chars": 10188,
"preview": "[](https://www.jstips.co/book/?utm_source"
},
{
"path": "_posts/en/angular/2016-01-01-angularjs-digest-vs-apply.md",
"chars": 2280,
"preview": "---\nlayout: post\n\ntitle: AngularJs - `$digest` vs `$apply`\ntip-number: 01\ntip-username: loverajoel \ntip-username-profile"
},
{
"path": "_posts/en/angular/2017-03-07-preventing-unwanted-scopes-creation-in-angularjs.md",
"chars": 1936,
"preview": "---\nlayout: post\n\ntitle: Preventing Unwanted Scopes Creation in AngularJs\ntip-number: 62\ntip-username: loverajoel \ntip-u"
},
{
"path": "_posts/en/javascript/2015-12-29-insert-item-inside-an-array.md",
"chars": 4723,
"preview": "---\nlayout: post\n\ntitle: Insert item inside an Array\n\ntip-number: 00\ntip-username: loverajoel\ntip-username-profile: http"
},
{
"path": "_posts/en/javascript/2016-01-03-improve-nested-conditionals.md",
"chars": 3081,
"preview": "---\nlayout: post\n\ntitle: Improve Nested Conditionals\ntip-number: 03\ntip-username: AlbertoFuente \ntip-username-profile: h"
},
{
"path": "_posts/en/javascript/2016-01-04-sorting-strings-with-accented-characters.md",
"chars": 3050,
"preview": "---\nlayout: post\n\ntitle: Sorting strings with accented characters\ntip-number: 04\ntip-username: loverajoel \ntip-username-"
},
{
"path": "_posts/en/javascript/2016-01-05-differences-between-undefined-and-null.md",
"chars": 1596,
"preview": "---\nlayout: post\n\ntitle: Differences between `undefined` and `null`\ntip-number: 05\ntip-username: loverajoel \ntip-usernam"
},
{
"path": "_posts/en/javascript/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md",
"chars": 1420,
"preview": "---\nlayout: post\n\ntitle: Writing a single method for arrays and a single element\ntip-number: 06\ntip-username: mattfxyz\nt"
},
{
"path": "_posts/en/javascript/2016-01-07-use-strict-and-get-lazy.md",
"chars": 2780,
"preview": "---\nlayout: post\n\ntitle: use strict and get lazy\ntip-number: 07\ntip-username: nainslie\ntip-username-profile: https://twi"
},
{
"path": "_posts/en/javascript/2016-01-08-converting-a-node-list-to-an-array.md",
"chars": 2233,
"preview": "---\nlayout: post\n\ntitle: Converting a Node List to an Array\ntip-number: 08\ntip-username: Tevko\ntip-username-profile: htt"
},
{
"path": "_posts/en/javascript/2016-01-09-template-strings.md",
"chars": 1523,
"preview": "---\nlayout: post\n\ntitle: Template Strings\ntip-number: 09\ntip-username: JakeRawr\ntip-username-profile: https://github.com"
},
{
"path": "_posts/en/javascript/2016-01-10-check-if-a-property-is-in-a-object.md",
"chars": 2154,
"preview": "---\nlayout: post\n\ntitle: Check if a property is in a Object\ntip-number: 10\ntip-username: loverajoel\ntip-username-profile"
},
{
"path": "_posts/en/javascript/2016-01-11-hoisting.md",
"chars": 1739,
"preview": "---\nlayout: post\n\ntitle: Hoisting\ntip-number: 11\ntip-username: squizzleflip\ntip-username-profile: https://twitter.com/sq"
},
{
"path": "_posts/en/javascript/2016-01-12-pseudomandatory-parameters-in-es6-functions.md",
"chars": 1556,
"preview": "---\nlayout: post\n\ntitle: Pseudomandatory parameters in ES6 functions\ntip-number: 12\ntip-username: Avraam Mavridis\ntip-us"
},
{
"path": "_posts/en/javascript/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md",
"chars": 1445,
"preview": "---\nlayout: post\n\ntitle: Tip to measure performance of a javascript block\ntip-number: 13\ntip-username: manmadareddy\ntip-"
},
{
"path": "_posts/en/javascript/2016-01-14-fat-arrow-functions.md",
"chars": 3848,
"preview": "---\nlayout: post\n\ntitle: Fat Arrow Functions\ntip-number: 14\ntip-username: pklinger\ntip-username-profile: https://github."
},
{
"path": "_posts/en/javascript/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md",
"chars": 2952,
"preview": "---\nlayout: post\n\ntitle: Even simpler way of using `indexOf` as a contains clause\ntip-number: 15\ntip-username: jhogoforb"
},
{
"path": "_posts/en/javascript/2016-01-16-passing-arguments-to-callback-functions.md",
"chars": 1714,
"preview": "---\nlayout: post\n\ntitle: Passing arguments to callback functions\ntip-number: 16\ntip-username: minhazav\ntip-username-prof"
},
{
"path": "_posts/en/javascript/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md",
"chars": 1100,
"preview": "---\nlayout: post\n\ntitle: Node.js - Run a module if it is not `required`\ntip-number: 17\ntip-username: odsdq\ntip-username-"
},
{
"path": "_posts/en/javascript/2016-01-18-rounding-the-fast-way.md",
"chars": 6137,
"preview": "---\nlayout: post\n\ntitle: Truncating the fast (but risky) way\ntip-number: 18\ntip-username: pklinger\ntip-username-profile:"
},
{
"path": "_posts/en/javascript/2016-01-19-safe-string-concatenation.md",
"chars": 1351,
"preview": "---\nlayout: post\n\ntitle: Safe string concatenation\ntip-number: 19\ntip-username: gogainda\ntip-username-profile: https://t"
},
{
"path": "_posts/en/javascript/2016-01-20-return-objects-to-enable-chaining-of-functions.md",
"chars": 915,
"preview": "---\nlayout: post\n\ntitle: Return objects to enable chaining of functions\ntip-number: 20\ntip-username: WakeskaterX\ntip-use"
},
{
"path": "_posts/en/javascript/2016-01-21-shuffle-an-array.md",
"chars": 825,
"preview": "---\nlayout: post\n\ntitle: Shuffle an Array\ntip-number: 21\ntip-username: 0xmtn\ntip-username-profile: https://github.com/0x"
},
{
"path": "_posts/en/javascript/2016-01-22-two-ways-to-empty-an-array.md",
"chars": 1746,
"preview": "---\nlayout: post\n\ntitle: Two ways to empty an array\ntip-number: 22\ntip-username: microlv\ntip-username-profile: https://g"
},
{
"path": "_posts/en/javascript/2016-01-23-converting-to-number-fast-way.md",
"chars": 823,
"preview": "---\nlayout: post\n\ntitle: Converting to number fast way\ntip-number: 23\ntip-username: sonnyt\ntip-username-profile: http://"
},
{
"path": "_posts/en/javascript/2016-01-24-use_===_instead_of_==.md",
"chars": 1050,
"preview": "---\nlayout: post\n\ntitle: Use === instead of ==\ntip-number: 24\ntip-username: bhaskarmelkani\ntip-username-profile: https:/"
},
{
"path": "_posts/en/javascript/2016-01-25-Using-immediately-invoked-function-expression.md",
"chars": 1748,
"preview": "---\nlayout: post\n\ntitle: Using immediately invoked function expression\ntip-number: 25\ntip-username: rishantagarwal \ntip-"
},
{
"path": "_posts/en/javascript/2016-01-26-filtering-and-sorting-a-list-of-strings.md",
"chars": 5031,
"preview": "---\nlayout: post\n\ntitle: Filtering and Sorting a List of Strings\ntip-number: 26\ntip-username: davegomez\ntip-username-pro"
},
{
"path": "_posts/en/javascript/2016-01-27-short-circuit-evaluation-in-js.md",
"chars": 2370,
"preview": "---\nlayout: post\n\ntitle: Short circuit evaluation in JS.\ntip-number: 27\ntip-username: bhaskarmelkani\ntip-username-profil"
},
{
"path": "_posts/en/javascript/2016-01-28-curry-vs-partial-application.md",
"chars": 2046,
"preview": "---\nlayout: post\n\ntitle: Currying vs partial application\ntip-number: 28\ntip-username: bhaskarmelkani\ntip-username-profil"
},
{
"path": "_posts/en/javascript/2016-01-29-speed-up-recursive-functions-with-memoization.md",
"chars": 2445,
"preview": "---\nlayout: post\n\ntitle: Speed up recursive functions with memoization\ntip-number: 29\ntip-username: hingsir\ntip-username"
},
{
"path": "_posts/en/javascript/2016-01-30-converting-truthy-falsy-values-to-boolean.md",
"chars": 757,
"preview": "---\nlayout: post\n\ntitle: Converting truthy/falsy values to boolean\ntip-number: 30\ntip-username: hakhag\ntip-username-prof"
},
{
"path": "_posts/en/javascript/2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md",
"chars": 2547,
"preview": "---\nlayout: post\n\ntitle: Avoid modifying or passing `arguments` into other functions — it kills optimization\ntip-number:"
},
{
"path": "_posts/en/javascript/2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md",
"chars": 2236,
"preview": "---\nlayout: post\n\ntitle: Map() to the rescue; adding order to Object properties\ntip-number: 32\ntip-username: loverajoel\n"
},
{
"path": "_posts/en/javascript/2016-02-02-create-range-0-n-easily-using-one-line.md",
"chars": 2095,
"preview": "---\nlayout: post\n\ntitle: Create array sequence `[0, 1, ..., N-1]` in one line\ntip-number: 33\ntip-username: SarjuHansaliy"
},
{
"path": "_posts/en/javascript/2016-02-03-implementing-asynchronous-loops.md",
"chars": 2357,
"preview": "---\nlayout: post\n\ntitle: Implementing asynchronous loop\ntip-number: 34\ntip-username: madmantalking\ntip-username-profile:"
},
{
"path": "_posts/en/javascript/2016-02-04-assignment-shorthands.md",
"chars": 2415,
"preview": "---\nlayout: post\n\ntitle: Assignment Operators\ntip-number: 35\ntip-username: hsleonis\ntip-username-profile: https://github"
},
{
"path": "_posts/en/javascript/2016-02-05-observe-dom-changes.md",
"chars": 2501,
"preview": "---\nlayout: post\n\ntitle: Observe DOM changes in extensions\ntip-number: 36\ntip-username: beyondns\ntip-username-profile: h"
},
{
"path": "_posts/en/javascript/2016-02-06-deduplicate-an-array.md",
"chars": 4050,
"preview": "---\nlayout: post\n\ntitle: Deduplicate an Array\ntip-number: 37\ntip-username: danillouz\ntip-username-profile: https://www.t"
},
{
"path": "_posts/en/javascript/2016-02-07-flattening-multidimensional-arrays-in-javascript.md",
"chars": 2322,
"preview": "---\nlayout: post\n\ntitle: Flattening multidimensional Arrays in JavaScript\ntip-number: 38\ntip-username: loverajoel\ntip-us"
},
{
"path": "_posts/en/javascript/2016-02-08-advanced-properties.md",
"chars": 4068,
"preview": "---\nlayout: post\n\ntitle: Advanced Javascript Properties\ntip-number: 39\ntip-username: mallowigi\ntip-username-profile: htt"
},
{
"path": "_posts/en/javascript/2016-02-09-using-json-stringify.md",
"chars": 1380,
"preview": "---\nlayout: post\n\ntitle: Using JSON.Stringify\ntip-number: 40\ntip-username: vamshisuram\ntip-username-profile: https://git"
},
{
"path": "_posts/en/javascript/2016-02-10-array-average-and-median.md",
"chars": 1541,
"preview": "---\nlayout: post\n\ntitle: Array average and median\ntip-number: 41\ntip-username: soyuka\ntip-username-profile: https://gith"
},
{
"path": "_posts/en/javascript/2016-02-11-preventing-unapply-attacks.md",
"chars": 2391,
"preview": "---\nlayout: post\n\ntitle: Preventing Unapply Attacks\ntip-number: 42\ntip-username: emars \ntip-username-profile: https://tw"
},
{
"path": "_posts/en/javascript/2016-02-12-use-destructuring-in-function-parameters.md",
"chars": 3830,
"preview": "---\nlayout: post\n\ntitle: Use destructuring in function parameters\ntip-number: 43\ntip-username: dislick \ntip-username-pro"
},
{
"path": "_posts/en/javascript/2016-02-13-know-the-passing-mechanism.md",
"chars": 2739,
"preview": "---\nlayout: post\n\ntitle: Know the passing mechanism\ntip-number: 44\ntip-username: bmkmanoj\ntip-username-profile: https://"
},
{
"path": "_posts/en/javascript/2016-02-14-calculate-the-max-min-value-from-an-array.md",
"chars": 1734,
"preview": "---\nlayout: post\n\ntitle: Calculate the Max/Min value from an array\ntip-number: 45\ntip-username: loverajoel\ntip-username-"
},
{
"path": "_posts/en/javascript/2016-02-15-detect-document-ready-in-pure-js.md",
"chars": 1166,
"preview": "---\nlayout: post\n\ntitle: Detect document ready in pure JS\ntip-number: 46\ntip-username: loverajoel\ntip-username-profile: "
},
{
"path": "_posts/en/javascript/2016-02-16-basics-declarations.md",
"chars": 3937,
"preview": "---\nlayout: post\n\ntitle: Basics declarations\ntip-number: 47\ntip-username: adaniloff \ntip-username-profile: https://githu"
},
{
"path": "_posts/en/javascript/2016-02-17-reminders-about-reduce-function-usage.md",
"chars": 3806,
"preview": "---\nlayout: post\n\ntitle: How to `reduce()` arrays\ntip-number: 48\ntip-username: darul75\ntip-username-profile: https://twi"
},
{
"path": "_posts/en/javascript/2016-02-26-extract-unix-timestamp-easily.md",
"chars": 1761,
"preview": "---\nlayout: post\n\ntitle: Easiest way to extract unix timestamp in JS\ntip-number: 49\ntip-username: nmrony\ntip-username-pr"
},
{
"path": "_posts/en/javascript/2016-03-03-helpful-console-log-hacks.md",
"chars": 2104,
"preview": "---\r\nlayout: post\r\n\r\ntitle: Helpful Console Logging Tricks\r\ntip-number: 50\r\ntip-username: zackhall\r\ntip-username-profile"
},
{
"path": "_posts/en/javascript/2016-03-16-DOM-event-listening-made-easy.md",
"chars": 1997,
"preview": "---\nlayout: post\n\ntitle: DOM event listening made easy\ntip-number: 51\ntip-username: octopitus\ntip-username-profile: http"
},
{
"path": "_posts/en/javascript/2016-04-05-return-values-with-the-new-operator.md",
"chars": 2917,
"preview": "---\nlayout: post\n\ntitle: Return Values with the 'new' Operator\ntip-number: 52\ntip-username: Morklympious\ntip-username-pr"
},
{
"path": "_posts/en/javascript/2016-04-21-get-file-extension.md",
"chars": 3541,
"preview": "---\nlayout: post\n\ntitle: Get File Extension\ntip-number: 53\ntip-username: richzw\ntip-username-profile: https://github.com"
},
{
"path": "_posts/en/javascript/2016-05-06-use-optional-arguments.md",
"chars": 2838,
"preview": "---\nlayout: post\n\ntitle: How to use optional arguments in functions (with optional callback)\ntip-number: 54\ntip-username"
},
{
"path": "_posts/en/javascript/2016-05-12-make-easy-loop-on-array.md",
"chars": 2578,
"preview": "---\nlayout: post\n\ntitle: Create an easy loop using an array\ntip-number: 55\ntip-username: jamet-julien\ntip-username-profi"
},
{
"path": "_posts/en/javascript/2016-08-02-copy-to-clipboard.md",
"chars": 1411,
"preview": "---\nlayout: post\n\ntitle: Copy to Clipboard\ntip-number: 56\ntip-username: loverajoel\ntip-username-profile: https://twitter"
},
{
"path": "_posts/en/javascript/2016-08-10-comma-operaton-in-js.md",
"chars": 1382,
"preview": "---\nlayout: post\n\ntitle: Comma operator in JS\ntip-number: 57\ntip-username: bhaskarmelkani\ntip-username-profile: https://"
},
{
"path": "_posts/en/javascript/2016-08-17-break-continue-loop-functional.md",
"chars": 2673,
"preview": "---\nlayout: post\n\ntitle: Breaking or continuing loop in functional programming\ntip-number: 58\ntip-username: vamshisuram\n"
},
{
"path": "_posts/en/javascript/2016-08-25-keyword-var-vs-let.md",
"chars": 3080,
"preview": "---\nlayout: post\n\ntitle: ES6, var vs let\ntip-number: 59\ntip-username: richzw\ntip-username-profile: https://github.com/ri"
},
{
"path": "_posts/en/javascript/2016-10-28-three-useful-hacks.md",
"chars": 1207,
"preview": "---\nlayout: post\n\ntitle: Three useful hacks\ntip-number: 60\ntip-username: leandrosimoes \ntip-username-profile: https://gi"
},
{
"path": "_posts/en/javascript/2017-01-19-binding-objects-to-functions.md",
"chars": 1394,
"preview": "---\nlayout: post\n\ntitle: Binding objects to functions\ntip-number: 61\ntip-username: loverajoel\ntip-username-profile: http"
},
{
"path": "_posts/en/javascript/2017-03-09-working-with-websocket-timeout.md",
"chars": 1317,
"preview": "---\nlayout: post\n\ntitle: Working With Websocket Timeout\ntip-number: 63\ntip-username: loverajoel \ntip-username-profile: h"
},
{
"path": "_posts/en/javascript/2017-03-12-3-array-hacks.md",
"chars": 2619,
"preview": "---\nlayout: post\n\ntitle: 3 Array Hacks\ntip-number: 64\ntip-username: hassanhelfi\ntip-username-profile: https://twitter.co"
},
{
"path": "_posts/en/javascript/2017-03-16-tapping-for-quick-debugging.md",
"chars": 2550,
"preview": "---\nlayout: post\n\ntitle: Tapping for quick debugging\ntip-number: 65\ntip-username: loverajoel\ntip-username-profile: https"
},
{
"path": "_posts/en/javascript/2017-03-29-recursion-iteration-and-tail-calls-in-js.md",
"chars": 4588,
"preview": "---\nlayout: post\n\ntitle: Recursion, iteration and tail calls in JS\ntip-number: 67\ntip-username: loverajoel\ntip-username-"
},
{
"path": "_posts/en/javascript/2017-04-03-why-you-should-use-Object.is()-in-equality-comparison.md",
"chars": 1688,
"preview": "---\nlayout: post\n\ntitle: Why you should use Object.is() in equality comparison \ntip-number: 68\ntip-username: TarekAlQadd"
},
{
"path": "_posts/en/javascript/2017-04-05-picking-and-rejecting-object-properties.md",
"chars": 1928,
"preview": "---\nlayout: post\n\ntitle: Picking and rejecting object properties \ntip-number: 70\ntip-username: loverajoel\ntip-username-p"
},
{
"path": "_posts/en/javascript/2017-04-11-protocols-for-the-brave.md",
"chars": 3001,
"preview": "---\nlayout: post\n\ntitle: Protocols for the Brave \ntip-number: 73\ntip-username: loverajoel\ntip-username-profile: https://"
},
{
"path": "_posts/en/javascript/2017-04-24-improving-your-async-functions-with-webworkers.md",
"chars": 2433,
"preview": "---\nlayout: post\n\ntitle: Improving your Async functions with WebWorkers\ntip-number: 74\ntip-username: loverajoel\ntip-user"
},
{
"path": "_posts/en/javascript/2017-06-14-closures-inside-loops.md",
"chars": 1318,
"preview": "---\nlayout: post\n\ntitle: Closures inside loops\ntip-number: 76\ntip-username: loverajoel\ntip-username-profile: https://git"
},
{
"path": "_posts/en/javascript/2017-06-14-immutable-structures-and-cloning.md",
"chars": 3098,
"preview": "---\nlayout: post\n\ntitle: Immutable structures and cloning\ntip-number: 78\ntip-username: loverajoel\ntip-username-profile: "
},
{
"path": "_posts/en/javascript/2017-06-15-looping-over-arrays.md",
"chars": 2767,
"preview": "---\nlayout: post\n\ntitle: Looping over arrays\ntip-number: 79\ntip-username: loverajoel\ntip-username-profile: https://githu"
},
{
"path": "_posts/en/javascript/2017-09-01-hash-maps-without-side-effects.md",
"chars": 1977,
"preview": "---\nlayout: post\n\ntitle: Hash maps without side effects\ntip-number: 73\ntip-username: bhaskarmelkani\ntip-username-profile"
},
{
"path": "_posts/en/javascript/2018-11-25-creating-immutable-objects-in-native-javascript.md",
"chars": 3017,
"preview": "---\nlayout: post\n\ntitle: Creating immutable objects in native JavaScript\ntip-number: 74\ntip-username: loverajoel\ntip-use"
},
{
"path": "_posts/en/javascript/2020-10-13-what-is-a-functional-inheritance.md",
"chars": 1352,
"preview": "---\nlayout: post\n\ntitle: What is Functional Inheritance?\ntip-number: 75\ntip-username: loverajoel\ntip-username-profile: h"
},
{
"path": "_posts/en/javascript/2020-10-15-what-is-a-currying-function.md",
"chars": 1195,
"preview": "---\nlayout: post\n\ntitle: What is a currying function?\ntip-number: 75\ntip-username: loverajoel\ntip-username-profile: http"
},
{
"path": "_posts/en/javascript/2020-10-20-what-is-the-temporal-dead-zone.md",
"chars": 1046,
"preview": "---\nlayout: post\n\ntitle: What is the Temporal Dead Zone?\ntip-number: 76\ntip-username: loverajoel\ntip-username-profile: h"
},
{
"path": "_posts/en/javascript/2020-10-22-difference-between-target-and-currentTarget.md",
"chars": 860,
"preview": "---\nlayout: post\n\ntitle: What is the difference between Target and currentTarget in the event context?\ntip-number: 77\nti"
},
{
"path": "_posts/en/javascript/2020-10-27-what-is-a-spread-operator.md",
"chars": 1168,
"preview": "---\nlayout: post\n\ntitle: What is a spread operator?\ntip-number: 78\ntip-username: loverajoel\ntip-username-profile: https:"
},
{
"path": "_posts/en/javascript/2020-11-04-what-is-a-void-operator.md",
"chars": 755,
"preview": "---\nlayout: post\n\ntitle: What is a void operator?\ntip-number: 79\ntip-username: loverajoel\ntip-username-profile: https://"
},
{
"path": "_posts/en/javascript/2020-11-17-what-is-the-promise-executor.md",
"chars": 785,
"preview": "---\nlayout: post\n\ntitle: What is the promise executor?\ntip-number: 80\ntip-username: loverajoel\ntip-username-profile: htt"
},
{
"path": "_posts/en/javascript/2021-02-02-what-is-the-javascript-ternary-operator.md",
"chars": 802,
"preview": "---\nlayout: post\n\ntitle: What is the JavaScript ternary operator?\ntip-number: 81\ntip-username: loverajoel\ntip-username-p"
},
{
"path": "_posts/en/more/2017-04-06-vuejs-how-vuejs-makes-a-copy-update-replace-inside-the-data-binding.md",
"chars": 2318,
"preview": "---\nlayout: post\n\ntitle: VueJS, How VueJS makes a copy-update-replace inside the data binding.\ntip-number: 71\ntip-userna"
},
{
"path": "_posts/en/react/2016-01-02-keys-in-children-components-are-important.md",
"chars": 2295,
"preview": "---\nlayout: post\n\ntitle: Keys in children components are important\ntip-number: 02\ntip-username: loverajoel \ntip-username"
},
{
"path": "_posts/en/react/2017-03-27-state-to-props-maps-with-memory.md",
"chars": 2918,
"preview": "---\nlayout: post\n\ntitle: State to Props maps with memory\ntip-number: 66\ntip-username: loverajoel \ntip-username-profile: "
},
{
"path": "_posts/en/react/2017-04-04-enhancing-react-components-composition.md",
"chars": 2968,
"preview": "---\nlayout: post\n\ntitle: Enhancing React components, Composition\ntip-number: 69\ntip-username: loverajoel \ntip-username-p"
},
{
"path": "_posts/en/react/2017-04-10-adventurers-guide-to-react.md",
"chars": 4844,
"preview": "---\nlayout: post\n\ntitle: Adventurers Guide to React (Part I)\ntip-number: 72\ntip-username: loverajoel \ntip-username-profi"
},
{
"path": "_posts/en/react/2017-05-29-upping-performance-by-appending-keying.md",
"chars": 1869,
"preview": "---\nlayout: post\n\ntitle: Upping Performance by Appending/Keying\ntip-number: 75\ntip-username: loverajoel \ntip-username-pr"
},
{
"path": "_posts/en/react/2021-07-18-trace-the-reason-make-your-page-rerender.md",
"chars": 2325,
"preview": "---\nlayout: post\n\ntitle: Check the reason make your page re-render by changed props and state \ntip-number: 74\ntip-userna"
},
{
"path": "_posts/es_ES/angular/2016-01-01-angularjs-digest-vs-apply.md",
"chars": 2428,
"preview": "---\nlayout: post\n\ntitle: AngularJs - `$digest` vs `$apply`\ntip-number: 01\ntip-username: loverajoel \ntip-username-profile"
},
{
"path": "_posts/es_ES/javascript/2015-12-29-insert-item-inside-an-array.md",
"chars": 1963,
"preview": "---\nlayout: post\n\ntitle: Insertar elemento dentro de un Array\ntip-number: 00\ntip-username: loverajoel \ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-01-03-improve-nested-conditionals.md",
"chars": 2719,
"preview": "---\nlayout: post\n\ntitle: Mejorar anidaciones Condicionales\ntip-number: 03\ntip-username: AlbertoFuente \ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-01-04-sorting-strings-with-accented-characters.md",
"chars": 3164,
"preview": "---\nlayout: post\n\ntitle: Ordenando cadenas con caracteres acentuados\ntip-number: 04\ntip-username: loverajoel \ntip-userna"
},
{
"path": "_posts/es_ES/javascript/2016-01-05-differences-between-undefined-and-null.md",
"chars": 1740,
"preview": "---\nlayout: post\n\ntitle: Diferencias entre `undefined` y `null`\ntip-number: 05\ntip-username: loverajoel \ntip-username-pr"
},
{
"path": "_posts/es_ES/javascript/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md",
"chars": 1396,
"preview": "---\nlayout: post\n\ntitle: Escribir un método único para los arrays y elemento unico\ntip-number: 06\ntip-username: mattfxyz"
},
{
"path": "_posts/es_ES/javascript/2016-01-07-use-strict-and-get-lazy.md",
"chars": 3133,
"preview": "---\nlayout: post\n\ntitle: Utilice strict y obtenga lazy\ntip-number: 07\ntip-username: nainslie\ntip-username-profile: https"
},
{
"path": "_posts/es_ES/javascript/2016-01-08-converting-a-node-list-to-an-array.md",
"chars": 1886,
"preview": "---\nlayout: post\n\ntitle: Convitiendo una Node List a un Array.\ntip-number: 08\ntip-username: Tevko\ntip-username-profile: "
},
{
"path": "_posts/es_ES/javascript/2016-01-09-template-strings.md",
"chars": 1201,
"preview": "---\nlayout: post\n\ntitle: Template Strings\ntip-number: 09\ntip-username: JakeRawr\ntip-username-profile: https://github.com"
},
{
"path": "_posts/es_ES/javascript/2016-01-10-check-if-a-property-is-in-a-object.md",
"chars": 2230,
"preview": "---\nlayout: post\n\ntitle: Averiguar si una propiedad está en un Objeto\ntip-number: 10\ntip-username: loverajoel\ntip-userna"
},
{
"path": "_posts/es_ES/javascript/2016-01-11-hoisting.md",
"chars": 1919,
"preview": "---\nlayout: post\n\ntitle: Hoisting\ntip-number: 11\ntip-username: squizzleflip\ntip-username-profile: https://twitter.com/sq"
},
{
"path": "_posts/es_ES/javascript/2016-01-12-pseudomandatory-parameters-in-es6-functions.md",
"chars": 1641,
"preview": "---\nlayout: post\n\ntitle: Pseudo parámetros obligatorios en funciones ES6\ntip-number: 12\ntip-username: Avraam Mavridis\nti"
},
{
"path": "_posts/es_ES/javascript/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md",
"chars": 1333,
"preview": "---\nlayout: post\n\ntitle: Tip para medir el rendimiento de un bloque de Javascript\ntip-number: 13\ntip-username: manmadare"
},
{
"path": "_posts/es_ES/javascript/2016-01-14-fat-arrow-functions.md",
"chars": 5066,
"preview": "---\nlayout: post\n\ntitle: Funciones de flechas de direcciones.\ntip-number: 14\ntip-username: pklinger\ntip-username-profile"
},
{
"path": "_posts/es_ES/javascript/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md",
"chars": 2940,
"preview": "---\nlayout: post\n\ntitle: Manera aún más sencilla de contener la cláusula al usar `indexOf`\ntip-number: 15\ntip-username: "
},
{
"path": "_posts/es_ES/javascript/2016-01-16-passing-arguments-to-callback-functions.md",
"chars": 1941,
"preview": "---\nlayout: post\n\ntitle: Paso de argumentos a las funciones de callback.\ntip-number: 16\ntip-username: minhazav\ntip-usern"
},
{
"path": "_posts/es_ES/javascript/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md",
"chars": 1124,
"preview": "---\nlayout: post\n\ntitle: Node.js - ejecutar un módulo si no es `required`\ntip-number: 17\ntip-username: odsdq\ntip-usernam"
},
{
"path": "_posts/es_ES/javascript/2016-01-18-rounding-the-fast-way.md",
"chars": 2269,
"preview": "---\nlayout: post\n\ntitle: Redondeo, la manera mas rápida\ntip-number: 18\ntip-username: pklinger\ntip-username-profile: http"
},
{
"path": "_posts/es_ES/javascript/2016-01-19-safe-string-concatenation.md",
"chars": 1388,
"preview": "---\nlayout: post\n\ntitle: Concatenación de Strings segura\ntip-number: 19\ntip-username: gogainda\ntip-username-profile: htt"
},
{
"path": "_posts/es_ES/javascript/2016-01-20-return-objects-to-enable-chaining-of-functions.md",
"chars": 909,
"preview": "---\nlayout: post\n\ntitle: Devolver los objetos que permiten el encadenamiento de las funciones\ntip-number: 20\ntip-usernam"
},
{
"path": "_posts/es_ES/javascript/2016-01-21-shuffle-an-array.md",
"chars": 822,
"preview": "---\nlayout: post\n\ntitle: Mezclar un Array\ntip-number: 21\ntip-username: 0xmtn\ntip-username-profile: https://github.com/0x"
},
{
"path": "_posts/es_ES/javascript/2016-01-22-two-ways-to-empty-an-array.md",
"chars": 2112,
"preview": "---\nlayout: post\n\ntitle: Dos formas de vacia un array\ntip-number: 22\ntip-username: microlv\ntip-username-profile: https:/"
},
{
"path": "_posts/es_ES/javascript/2016-01-23-converting-to-number-fast-way.md",
"chars": 940,
"preview": "---\nlayout: post\n\ntitle: Convertir a numero de la forma mas rapida\ntip-number: 23\ntip-username: sonnyt\ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-01-24-use_===_instead_of_==.md",
"chars": 1102,
"preview": "---\nlayout: post\n\ntitle: Utilizar === en lugar de ==\ntip-number: 24\ntip-username: bhaskarmelkani\ntip-username-profile: h"
},
{
"path": "_posts/es_ES/javascript/2016-01-25-Using-immediately-invoked-function-expression.md",
"chars": 1883,
"preview": "---\nlayout: post\n\ntitle: Invocar una funcion inmediatamente\ntip-number: 25\ntip-username: rishantagarwal \ntip-username-pr"
},
{
"path": "_posts/es_ES/javascript/2016-01-26-filtering-and-sorting-a-list-of-strings.md",
"chars": 4971,
"preview": "---\nlayout: post\n\ntitle: Filtrar y ordenar una lista de Strings\ntip-number: 26\ntip-username: davegomez\ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-01-27-short-circiut-evaluation-in-js.md",
"chars": 2434,
"preview": "---\nlayout: post\n\ntitle: Evaluación de Short circuit en JS.\ntip-number: 27\ntip-username: bhaskarmelkani\ntip-username-pro"
},
{
"path": "_posts/es_ES/javascript/2016-01-28-curry-vs-partial-application.md",
"chars": 2056,
"preview": "---\nlayout: post\n\ntitle: Currying vs partial application\ntip-number: 28\ntip-username: bhaskarmelkani\ntip-username-profil"
},
{
"path": "_posts/es_ES/javascript/2016-01-29-speed-up-recursive-functions-with-memoization.md",
"chars": 2068,
"preview": "---\nlayout: post\n\ntitle: Acelerar las funciones recursivas con memoization\ntip-number: 29\ntip-username: hingsir\ntip-user"
},
{
"path": "_posts/es_ES/javascript/2016-01-30-converting-truthy-falsy-values-to-boolean.md",
"chars": 798,
"preview": "---\nlayout: post\n\ntitle: Convertir valores truthy/falsy a boolean\ntip-number: 30\ntip-username: hakhag\ntip-username-profi"
},
{
"path": "_posts/es_ES/javascript/2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md",
"chars": 2683,
"preview": "---\nlayout: post\n\ntitle: Evitar la modificación o pasando `arguments` en otras funciones - mata la optimización\n\ntip-num"
},
{
"path": "_posts/es_ES/javascript/2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md",
"chars": 2367,
"preview": "---\nlayout: post\n\ntitle: Map() al rescate; añadir orden a las propiedades de los Objetos.\ntip-number: 32\ntip-username: l"
},
{
"path": "_posts/es_ES/javascript/2016-02-02-create-range-0-n-easily-using-one-line.md",
"chars": 1566,
"preview": "---\nlayout: post\n\n\ntitle: Crear rangos 0...(N-1) facilmente usando una linea\ntip-number: 33\ntip-username: SarjuHansaliya"
},
{
"path": "_posts/es_ES/javascript/2016-02-03-implementing-asynchronous-loops.md",
"chars": 2399,
"preview": "---\nlayout: post\n\ntitle: Implementación de bucle asíncrono.\ntip-number: 34\ntip-username: madmantalking\ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-02-04-assignment-shorthands.md",
"chars": 2016,
"preview": "---\nlayout: post\n\ntitle: Operadores de Asignación\ntip-number: 35\ntip-username: hsleonis\ntip-username-profile: https://gi"
},
{
"path": "_posts/es_ES/javascript/2016-02-05-observe-dom-changes.md",
"chars": 2658,
"preview": "---\nlayout: post\n\ntitle: Observar los cambios del DOM en extensiones.\ntip-number: 36\ntip-username: beyondns\ntip-username"
},
{
"path": "_posts/es_ES/javascript/2016-02-06-deduplicate-an-array.md",
"chars": 4362,
"preview": "---\nlayout: post\n\ntitle: Deduplique un Array\ntip-number: 37\ntip-username: danillouz\ntip-username-profile: https://www.tw"
},
{
"path": "_posts/es_ES/javascript/2016-02-07-flattening-multidimensional-arrays-in-javascript.md",
"chars": 1865,
"preview": "---\nlayout: post\n\ntitle: Arrays multidimensionales en JavaScript\ntip-number: 38\ntip-username: loverajoel\ntip-username-pr"
},
{
"path": "_posts/es_ES/javascript/2016-02-08-advanced-properties.md",
"chars": 4305,
"preview": "---\nlayout: post\n\ntitle: Propiedades avanzadas de Javascript\ntip-number: 39\ntip-username: mallowigi\ntip-username-profile"
},
{
"path": "_posts/es_ES/javascript/2016-02-09-using-json-stringify.md",
"chars": 1516,
"preview": "---\nlayout: post\n\ntitle: Usando JSON.Stringify\ntip-number: 40\ntip-username: vamshisuram\ntip-username-profile: https://gi"
},
{
"path": "_posts/es_ES/javascript/2016-02-10-array-average-and-median.md",
"chars": 1634,
"preview": "---\nlayout: post\n\ntitle: Array media y promedio.\ntip-number: 41\ntip-username: soyuka\ntip-username-profile: https://githu"
},
{
"path": "_posts/es_ES/javascript/2016-02-11-preventing-unapply-attacks.md",
"chars": 2592,
"preview": "---\nlayout: post\n\ntitle: La prevención de ataques de cancelar la aplicación\ntip-number: 42\ntip-username: emars \ntip-user"
},
{
"path": "_posts/es_ES/javascript/2016-02-12-use-destructuring-in-function-parameters.md",
"chars": 1120,
"preview": "---\nlayout: post\n\ntitle: Utilice la desestructuración de los parámetros de función\ntip-number: 43\ntip-username: dislick "
},
{
"path": "_posts/es_ES/javascript/2016-02-13-know-the-passing-mechanism.md",
"chars": 2901,
"preview": "---\nlayout: post\n\ntitle: Conocer el mecanismo de paso\ntip-number: 44\ntip-username: bmkmanoj\ntip-username-profile: https:"
},
{
"path": "_posts/es_ES/javascript/2016-02-14-calculate-the-max-min-value-from-an-array.md",
"chars": 1733,
"preview": "---\nlayout: post\n\ntitle: Calcular el valor Max/Min de un array\ntip-number: 45\ntip-username: loverajoel\ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-02-15-detect-document-ready-in-pure-js.md",
"chars": 1189,
"preview": "---\nlayout: post\n\ntitle: Detectar cuando DOM esta listo en JS puro\ntip-number: 46\ntip-username: loverajoel\ntip-username-"
},
{
"path": "_posts/es_ES/javascript/2016-02-16-basics-declarations.md",
"chars": 4024,
"preview": "---\nlayout: post\n\ntitle: Declaraciones basicas\ntip-number: 47\ntip-username: adaniloff \ntip-username-profile: https://git"
},
{
"path": "_posts/es_ES/javascript/2016-02-17-reminders-about-reduce-function-usage.md",
"chars": 3994,
"preview": "---\nlayout: post\n\ntitle: Reducir el uso de la función incorporada\ntip-number: 48\ntip-username: darul75\ntip-username-prof"
},
{
"path": "_posts/es_ES/javascript/2016-02-26-extract-unix-timestamp-easily.md",
"chars": 1866,
"preview": "---\nlayout: post\n\ntitle: La manera más fácil de extraer marca de tiempo Unix en JS\ntip-number: 49\ntip-username: nmrony\nt"
},
{
"path": "_posts/es_ES/javascript/2016-03-03-helpful-console-log-hacks.md",
"chars": 2187,
"preview": "---\r\nlayout: post\r\n\r\ntitle: Utiles trucos para Console Logging\r\ntip-number: 50\r\ntip-username: zackhall\r\ntip-username-pro"
},
{
"path": "_posts/es_ES/javascript/2016-03-16-DOM-event-listening-made-easy.md",
"chars": 2103,
"preview": "---\nlayout: post\n\ntitle: Escuchar eventos DOM mas simple\ntip-number: 51\ntip-username: octopitus\ntip-username-profile: ht"
},
{
"path": "_posts/es_ES/javascript/2016-04-05-return-values-with-the-new-operator.md",
"chars": 2948,
"preview": "---\nlayout: post\n\ntitle: Retorno de valores con el operador 'new'\ntip-number: 52\ntip-username: Morklympious\ntip-username"
},
{
"path": "_posts/es_ES/javascript/2016-04-21-get-file-extension.md",
"chars": 3637,
"preview": "---\nlayout: post\n\ntitle: Obtener extensión de archivo\ntip-number: 53\ntip-username: richzw\ntip-username-profile: https://"
},
{
"path": "_posts/es_ES/javascript/2016-05-06-use-optional-arguments.md",
"chars": 2946,
"preview": "---\nlayout: post\n\ntitle: Cómo utilizar argumentos opcionales en funciones (con callback opcional)\ntip-number: 54\ntip-use"
},
{
"path": "_posts/es_ES/javascript/2016-05-12-make-easy-loop-on-array.md",
"chars": 2627,
"preview": "---\nlayout: post\n\ntitle: Crear un bucle fácil usando un array\ntip-number: 55\ntip-username: jamet-julien\ntip-username-pro"
},
{
"path": "_posts/es_ES/react/2016-01-02-keys-in-children-components-are-important.md",
"chars": 2428,
"preview": "---\nlayout: post\n\ntitle: Keys en componentes secundarios son importantes\ntip-number: 02\ntip-username: loverajoel \ntip-us"
},
{
"path": "_posts/zh_CN/angular/2016-01-01-angularjs-digest-vs-apply.md",
"chars": 1153,
"preview": "---\nlayout: post\n\ntitle: AngularJs - $digest vs $apply\ntip-number: 01\ntip-username: loverajoel \ntip-username-profile: ht"
},
{
"path": "_posts/zh_CN/javascript/2015-12-29-insert-item-inside-an-array.md",
"chars": 3547,
"preview": "---\nlayout: post\n\ntitle: 向数组中插入元素\ntip-number: 00\ntip-username: loverajoel \ntip-username-profile: https://github.com/love"
},
{
"path": "_posts/zh_CN/javascript/2016-01-03-improve-nested-conditionals.md",
"chars": 2251,
"preview": "---\nlayout: post\n\ntitle: 优化嵌套的条件语句\ntip-number: 03\ntip-username: AlbertoFuente \ntip-username-profile: https://github.com/"
},
{
"path": "_posts/zh_CN/javascript/2016-01-04-sorting-strings-with-accented-characters.md",
"chars": 2305,
"preview": "---\nlayout: post\n\ntitle: 排列含音节字母的字符串\ntip-number: 04\ntip-username: loverajoel \ntip-username-profile: https://github.com/l"
},
{
"path": "_posts/zh_CN/javascript/2016-01-05-differences-between-undefined-and-null.md",
"chars": 1227,
"preview": "---\nlayout: post\n\ntitle: undefined与null的区别\ntip-number: 05\ntip-username: loverajoel \ntip-username-profile: https://github"
},
{
"path": "_posts/zh_CN/javascript/2016-01-06-writing-a-single-method-for-arrays-and-a-single-element.md",
"chars": 879,
"preview": "---\nlayout: post\n\ntitle: 可以接受单参数与数组的方法\ntip-number: 06\ntip-username: mattfxyz\ntip-username-profile: https://twitter.com/m"
},
{
"path": "_posts/zh_CN/javascript/2016-01-07-use-strict-and-get-lazy.md",
"chars": 1538,
"preview": "---\nlayout: post\n\ntitle: 使用\"use strict\" 变得懒惰\ntip-number: 07\ntip-username: nainslie\ntip-username-profile: https://twitter"
},
{
"path": "_posts/zh_CN/javascript/2016-01-08-converting-a-node-list-to-an-array.md",
"chars": 1579,
"preview": "---\nlayout: post\n\ntitle: 将Node List转换为数组(Array)\ntip-number: 08\ntip-username: Tevko\ntip-username-profile: https://twitter"
},
{
"path": "_posts/zh_CN/javascript/2016-01-09-template-strings.md",
"chars": 1134,
"preview": "---\nlayout: post\n\ntitle: 模板字符串\ntip-number: 09\ntip-username: JakeRawr\ntip-username-profile: https://github.com/JakeRawr\nt"
},
{
"path": "_posts/zh_CN/javascript/2016-01-10-check-if-a-property-is-in-a-object.md",
"chars": 1488,
"preview": "---\nlayout: post\n\ntitle: 检查某对象是否有某属性\ntip-number: 10\ntip-username: loverajoel\ntip-username-profile: https://www.twitter.c"
},
{
"path": "_posts/zh_CN/javascript/2016-01-11-hoisting.md",
"chars": 1219,
"preview": "---\nlayout: post\n\ntitle: 变量提升\ntip-number: 11\ntip-username: squizzleflip\ntip-username-profile: https://twitter.com/squizz"
},
{
"path": "_posts/zh_CN/javascript/2016-01-12-pseudomandatory-parameters-in-es6-functions.md",
"chars": 993,
"preview": "---\nlayout: post\n\ntitle: ES6中的伪强制参数\ntip-number: 12\ntip-username: Avraam Mavridis\ntip-username-profile: https://github.co"
},
{
"path": "_posts/zh_CN/javascript/2016-01-13-tip-to-measure-performance-of-a-javascript-block.md",
"chars": 1210,
"preview": "---\nlayout: post\n\ntitle: 测量javascript代码块性能的小知识\ntip-number: 13\ntip-username: manmadareddy\ntip-username-profile: https://"
},
{
"path": "_posts/zh_CN/javascript/2016-01-14-fat-arrow-functions.md",
"chars": 2623,
"preview": "---\nlayout: post\n\ntitle: 箭头函数\ntip-number: 14\ntip-username: pklinger\ntip-username-profile: https://github.com/pklinger/\nt"
},
{
"path": "_posts/zh_CN/javascript/2016-01-15-even-simpler-way-of-using-indexof-as-a-contains-clause.md",
"chars": 2400,
"preview": "---\nlayout: post\n\ntitle: 更简单的使用indexOf实现contains功能\ntip-number: 15\ntip-username: jhogoforbroke\ntip-username-profile: http"
},
{
"path": "_posts/zh_CN/javascript/2016-01-16-passing-arguments-to-callback-functions.md",
"chars": 1115,
"preview": "---\nlayout: post\n\ntitle: 向回调方法传递参数\ntip-number: 16\ntip-username: minhazav\ntip-username-profile: https://twitter.com/minha"
},
{
"path": "_posts/zh_CN/javascript/2016-01-17-nodejs-run-a-module-if-it-is-not-required.md",
"chars": 782,
"preview": "---\nlayout: post\n\ntitle: Node.js - 运行未被引用的模块\ntip-number: 17\ntip-username: odsdq\ntip-username-profile: https://twitter.co"
},
{
"path": "_posts/zh_CN/javascript/2016-01-18-rounding-the-fast-way.md",
"chars": 3275,
"preview": "---\nlayout: post\n\ntitle: 快速(但危险)的取整方法\ntip-number: 18\ntip-username: pklinger\ntip-username-profile: https://github.com/pkl"
},
{
"path": "_posts/zh_CN/javascript/2016-01-19-safe-string-concatenation.md",
"chars": 860,
"preview": "---\nlayout: post\n\ntitle: 安全的字符串拼接\ntip-number: 19\ntip-username: gogainda\ntip-username-profile: https://twitter.com/gogain"
},
{
"path": "_posts/zh_CN/javascript/2016-01-20-return-objects-to-enable-chaining-of-functions.md",
"chars": 688,
"preview": "---\nlayout: post\n\ntitle: 返回对象,使方法可以链式调用\ntip-number: 20\ntip-username: WakeskaterX\ntip-username-profile: https://twitter.c"
},
{
"path": "_posts/zh_CN/javascript/2016-01-21-shuffle-an-array.md",
"chars": 750,
"preview": "---\nlayout: post\n\ntitle: 对数组洗牌\ntip-number: 21\ntip-username: 0xmtn\ntip-username-profile: https://github.com/0xmtn/\ntip-tl"
},
{
"path": "_posts/zh_CN/javascript/2016-01-22-two-ways-to-empty-an-array.md",
"chars": 1084,
"preview": "---\nlayout: post\n\ntitle: 清空数组的两种方法\ntip-number: 22\ntip-username: microlv\ntip-username-profile: https://github.com/microlv"
},
{
"path": "_posts/zh_CN/javascript/2016-01-23-converting-to-number-fast-way.md",
"chars": 544,
"preview": "---\nlayout: post\n\ntitle: 转换为数字的更快方法\ntip-number: 23\ntip-username: sonnyt\ntip-username-profile: http://twitter.com/sonnyt\n"
},
{
"path": "_posts/zh_CN/javascript/2016-01-24-use_===_instead_of_==.md",
"chars": 722,
"preview": "---\nlayout: post\n\ntitle: 使用 === 而不是 ==\ntip-number: 24\ntip-username: bhaskarmelkani\ntip-username-profile: https://www.twi"
},
{
"path": "_posts/zh_CN/javascript/2016-01-25-Using-immediately-invoked-function-expression.md",
"chars": 1180,
"preview": "---\nlayout: post\n\ntitle: 使用立即执行函数表达式\ntip-number: 25\ntip-username: rishantagarwal \ntip-username-profile: https://github.c"
},
{
"path": "_posts/zh_CN/javascript/2016-01-26-filtering-and-sorting-a-list-of-strings.md",
"chars": 4158,
"preview": "---\nlayout: post\n\ntitle: 过滤并排序字符串列表\ntip-number: 26\ntip-username: davegomez\ntip-username-profile: https://github.com/dave"
},
{
"path": "_posts/zh_CN/javascript/2016-01-27-short-circuit-evaluation-in-js.md",
"chars": 1613,
"preview": "---\nlayout: post\n\ntitle: JS中的短路求值\ntip-number: 27\ntip-username: bhaskarmelkani\ntip-username-profile: https://www.twitter."
},
{
"path": "_posts/zh_CN/javascript/2016-01-28-curry-vs-partial-application.md",
"chars": 1420,
"preview": "---\nlayout: post\n\ntitle: 柯里化(currying)与部分应用(partial application)\ntip-number: 28\ntip-username: bhaskarmelkani\ntip-usernam"
},
{
"path": "_posts/zh_CN/javascript/2016-01-29-speed-up-recursive-functions-with-memoization.md",
"chars": 1781,
"preview": "---\nlayout: post\n\ntitle: 运用存储加速递归 Speed up recursive functions with memoization\ntip-number: 29\ntip-username: hingsir\ntip"
},
{
"path": "_posts/zh_CN/javascript/2016-01-30-converting-truthy-falsy-values-to-boolean.md",
"chars": 618,
"preview": "---\nlayout: post\n\ntitle: 将truthy/falsy转换为布尔值\ntip-number: 30\ntip-username: hakhag\ntip-username-profile: https://github.co"
},
{
"path": "_posts/zh_CN/javascript/2016-01-31-avoid-modifying-or-passing-arguments-into-other-functions—it-kills-optimization.md",
"chars": 1437,
"preview": "---\nlayout: post\n\ntitle: 避免修改和传递`arguments`给其他方法 — 影响优化\ntip-number: 31\ntip-username: berkana\ntip-username-profile: https"
},
{
"path": "_posts/zh_CN/javascript/2016-02-01-map-to-the-rescue-adding-order-to-object-properties.md",
"chars": 1528,
"preview": "---\nlayout: post\n\ntitle: Map()的营救;使对象属性有顺序\ntip-number: 32\ntip-username: loverajoel\ntip-username-profile: https://twitter"
},
{
"path": "_posts/zh_CN/javascript/2016-02-02-create-range-0-n-easily-using-one-line.md",
"chars": 1621,
"preview": "---\nlayout: post\n\ntitle: 仅用一行生成`[0, 1, ..., N-1]`数列\ntip-number: 33\ntip-username: SarjuHansaliya\ntip-username-profile: ht"
},
{
"path": "_posts/zh_CN/javascript/2016-02-03-implementing-asynchronous-loops.md",
"chars": 1476,
"preview": "---\nlayout: post\n\ntitle: 实现异步循环\ntip-number: 34\ntip-username: madmantalking\ntip-username-profile: https://github.com/madm"
},
{
"path": "_posts/zh_CN/javascript/2016-02-04-assignment-shorthands.md",
"chars": 1656,
"preview": "---\nlayout: post\n\ntitle: 赋值技巧\ntip-number: 35\ntip-username: hsleonis\ntip-username-profile: https://github.com/hsleonis\nti"
},
{
"path": "_posts/zh_CN/javascript/2016-02-05-observe-dom-changes.md",
"chars": 2140,
"preview": "---\nlayout: post\n\ntitle: 扩展插件中观察DOM的变化\ntip-number: 36\ntip-username: beyondns\ntip-username-profile: https://github.com/be"
},
{
"path": "_posts/zh_CN/javascript/2016-02-06-deduplicate-an-array.md",
"chars": 3340,
"preview": "---\nlayout: post\n\ntitle: 数组去重\ntip-number: 37\ntip-username: danillouz\ntip-username-profile: https://www.twitter.com/danil"
},
{
"path": "_posts/zh_CN/javascript/2016-02-07-flattening-multidimensional-arrays-in-javascript.md",
"chars": 2011,
"preview": "---\nlayout: post\n\ntitle: Javascript多维数组扁平化\ntip-number: 38\ntip-username: loverajoel\ntip-username-profile: https://www.twi"
},
{
"path": "_posts/zh_CN/javascript/2016-02-08-advanced-properties.md",
"chars": 2670,
"preview": "---\nlayout: post\n\ntitle: Javascript高级特性\ntip-number: 39\ntip-username: mallowigi\ntip-username-profile: https://github.com/"
},
{
"path": "_posts/zh_CN/javascript/2016-02-09-using-json-stringify.md",
"chars": 1117,
"preview": "---\nlayout: post\n\ntitle: 使用JSON.Stringify\ntip-number: 40\ntip-username: vamshisuram\ntip-username-profile: https://github."
},
{
"path": "_posts/zh_CN/javascript/2016-02-10-array-average-and-median.md",
"chars": 1390,
"preview": "---\nlayout: post\n\ntitle: 数组平均值与中值\ntip-number: 41\ntip-username: soyuka\ntip-username-profile: https://github.com/soyuka\nti"
},
{
"path": "_posts/zh_CN/javascript/2016-02-11-preventing-unapply-attacks.md",
"chars": 1472,
"preview": "---\nlayout: post\n\ntitle: 预防unapply攻击\ntip-number: 42\ntip-username: emars \ntip-username-profile: https://twitter.com/marse"
},
{
"path": "_posts/zh_CN/javascript/2016-02-12-use-destructuring-in-function-parameters.md",
"chars": 2746,
"preview": "---\nlayout: post\n\ntitle: 函数参数内使用解构\ntip-number: 43\ntip-username: dislick \ntip-username-profile: https://github.com/dislic"
},
{
"path": "_posts/zh_CN/javascript/2016-02-13-know-the-passing-mechanism.md",
"chars": 1423,
"preview": "---\nlayout: post\n\ntitle: 了解传值机制\ntip-number: 44\ntip-username: bmkmanoj\ntip-username-profile: https://github.com/bmkmanoj\n"
},
{
"path": "_posts/zh_CN/javascript/2016-02-14-calculate-the-max-min-value-from-an-array.md",
"chars": 1259,
"preview": "---\nlayout: post\n\ntitle: 计算数组中的最大值/最小值\ntip-number: 45\ntip-username: loverajoel\ntip-username-profile: https://www.twitter"
},
{
"path": "_posts/zh_CN/javascript/2016-02-15-detect-document-ready-in-pure-js.md",
"chars": 991,
"preview": "---\nlayout: post\n\ntitle: 纯JS监听document是否加载完成\ntip-number: 46\ntip-username: loverajoel\ntip-username-profile: https://www.t"
}
]
// ... and 96 more files (download for full content)
About this extraction
This page contains the full source code of the loverajoel/jstips GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 296 files (603.4 KB), approximately 210.3k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.