├── .editorconfig ├── .gitattributes ├── .gitignore ├── .travis.yml ├── 9781484253939.jpg ├── LICENSE.txt ├── README.md ├── errata.md ├── package.json ├── src ├── chapter01 │ ├── 030-var-overwriting.js │ ├── 031-simulate-dom.js │ ├── 090-let-variables.js │ ├── 100-simulate-dom-with-let.js │ ├── 110-let-hoisted.js │ ├── 120-let-and-switch.js │ ├── 130-iefe-for-var.js │ ├── 140-eliminate-iefe-with-let.js │ ├── 150-const-reference-cannot-change.js │ └── desktop.ini ├── chapter02 │ ├── 010-function-statement.js │ ├── 020-function-expression.js │ ├── 025-function-statement-vs-expression.js │ ├── 030-arrays-manipulation-with-function-expression.js │ ├── 040-fat-arrow-syntax.js │ ├── 050-arrow-parameters.js │ ├── 060-arrow-block-body.js │ ├── 070-arrow-block-confusing.js │ ├── 080-arrow-block-parenthesis.js │ ├── 090-function-expression-invocation-patterns.js │ ├── 120-arrow-expression-and-this.js │ ├── 125-arrow-functions-as-constructors-no-arguments.js │ ├── 130-arrays-manipulation-with-arrow-functions.js │ ├── 140-knowing-what-this-arrow-functions.js │ ├── 150-make-and-using-arrow-functions.js │ └── desktop.ini ├── chapter03 │ ├── 010-function-multi-arity.js │ ├── 020-function-default-checks.js │ ├── 030-function-default-args.js │ ├── 040-expression-default-param.js │ ├── 050-rectangle.js │ ├── 060-triangle.js │ ├── 080-default-before-required.js │ ├── 090-using-arguments.js │ ├── 100-arguments-against-arguments.js │ ├── 110-rest-params-instead-of-arguments.js │ ├── 120-rest-params-length.js │ └── desktop.ini ├── chapter04 │ ├── 010-convoluted-lookup.js │ ├── 020-perimeter-apply.js │ ├── 030-perimeter-spread.js │ ├── 040-spread-console-log.js │ ├── 050-spread-create-concatenate-arrays.js │ ├── 060-spread-rest-together.js │ ├── 065-object-api-defineProperties-enumerable.js │ ├── 067-object-api-defineProperties-enumerable.js │ ├── 068-object-assign.js │ ├── 069-object-spread.js │ ├── 070-array-destructuring.js │ ├── 080-array-destructuring-defaults.js │ ├── 090-array-destructuring-function-parameter.js │ ├── 100-array-destructuring-rest.js │ ├── 110-recursive-or.js │ ├── 120-array-nested-destructuring.js │ ├── 121-multiple-returns.js │ ├── 125-destruct-rest-params.js │ ├── 130-object-destructuring.js │ ├── 140-object-destructuring-all.js │ ├── 150-convoluted-lookup-with-destructuring.js │ └── desktop.ini ├── chapter05 │ ├── 005-interpolation.js │ ├── 010-simple-template-literal.js │ ├── 020-nested-interpolation.js │ ├── 030-escaping-literals.js │ ├── 040-static-vs-dynamic.js │ ├── 050-reimplement-template-strings.js │ ├── 060-emmet-handler.js │ └── desktop.ini ├── chapter06 │ ├── 010-objects-keys-strings.js │ ├── 020-maps-construction-manipulation.js │ ├── 030-maps-whole-manipulation.js │ ├── 040-spreading-maps.js │ ├── 050-maps-from-other-maps.js │ ├── 055-no-literals-for-maps.js │ ├── 060-maps-to-from-json.js │ ├── 070-maps-to-from-json-fail.js │ ├── 080-maps-hard-references.js │ ├── 090-sets-construction-manipulation.js │ ├── 100-sets-whole-manipulation.js │ ├── 110-sets-from-other-set.js │ ├── 120-use-for-weaksets.js │ └── desktop.ini ├── chapter07 │ ├── 010-object-literal-getters-setters.js │ ├── 020-object-literal-computed-property.js │ ├── 025-revealing-module-pattern.js │ ├── 050-object-literal-method-shorthand.js │ ├── 060-object-literal-inline-computed-property.js │ ├── 070-revealing-module-pattern-shorthand.js │ ├── 080-trailing-comma-arrays-objects.js │ ├── 090-trailing-comma-functions.js │ └── desktop.ini ├── chapter08 │ ├── 020-method-hook-using-strings.js │ ├── 040-symbols-are-unique.js │ ├── 050-overriding-object-keys-with-symbols.js │ ├── 070-method-hook-using-symbols.js │ ├── 080-switch-case-using-strings.js │ ├── 090-switch-case-using-symbols.js │ ├── 100-symbol-for.js │ ├── 110-symbol-keyFor.js │ ├── 120-string-match.js │ ├── 130-symbol-match.js │ ├── 140-object-enumerate-keys.js │ └── desktop.ini ├── chapter09 │ ├── 010-for-in-loop-arrays.js │ ├── 020-es5-fibonacci.js │ ├── 030-simple-iterable.js │ ├── 035-for-of-loop-array.js │ ├── 040-loops-for-of-all-datastructures.js │ ├── 045-iterator-return.js │ ├── 050-simple-generator.js │ ├── 060-generator-fibonacci.js │ ├── 070-simple-generator-push.js │ ├── 080-generator-return.js │ ├── 090-yield-generator.js │ └── desktop.ini ├── chapter10 │ ├── 010-basic-promise.js │ ├── 020-promisify-xhr.js │ ├── 025-promisify-xhr-with-then-catch.js │ ├── 030-promise-all.js │ ├── 040-promise-race.js │ └── desktop.ini ├── chapter11 │ ├── 010-basic-class.js │ ├── 015-basic-prototypal-inheritance.js │ ├── 020-classes.js │ ├── 030-classes-prototypal-inheritance.js │ ├── 040-classes-static-methods.js │ └── desktop.ini ├── chapter12 │ ├── 010-iefe-for-var.js │ ├── 020-named-inline-exports.js │ ├── 030-named-exports.js │ ├── 040-default-exports.js │ ├── 050-alias-exports.js │ ├── 060-named-imports.js │ ├── 070-named-aliased-import.js │ ├── 080-wildcard-import.js │ ├── 090-aliasing-imports.js │ ├── 100-default-import.js │ ├── 110-default-with-aliased-imports.js │ ├── desktop.ini │ ├── exporter.mjs │ └── importer.mjs ├── chapter13 │ ├── 010-array-prototype-equals.js │ ├── 020-intercept-method.js │ ├── 030-simple-proxy.js │ ├── 040-intercept-method-calls.js │ ├── 050-array-prototype-equals-using-proxy.js │ ├── 060-singleton-using-proxies.js │ ├── 080-xml-builder.js │ └── desktop.ini ├── chapter14 │ ├── 010-simple-math-imperatively.js │ ├── 020-simple-math-using-promises.js │ ├── 025-sync-async-conditional.js │ ├── 030-simple-async.js │ ├── 040-simple-async-await.js │ ├── 050-simple-math-using-async-await.js │ ├── 055-sync-async-conditional-again.js │ ├── 060-fetch-with-async-await.js │ ├── 065-error-trapping.js │ ├── 070-too-much-waiting.js │ └── desktop.ini ├── chapter15 │ ├── 010-asynchronous-iteration.js │ ├── 020-asynchronous-generator-async-await.js │ ├── 030-simple-sync-generator.js │ ├── 040-simple-async-iterable.js │ ├── 050-simple-async-iterable-for-async-await.js │ ├── 060-simple-async-iterable-return.js │ ├── 070-simple-async-iterable-try-catch.js │ ├── 080-for-await-of-sync-iterable.js │ ├── 090-aync-generator.js │ └── desktop.ini └── desktop.ini ├── test ├── .eslintrc ├── chapter01 │ ├── 030-var-overwritingSpec.js │ ├── 031-simulate-domSpec.js │ ├── 090-let-variablesSpec.js │ ├── 100-simulate-dom-with-letSpec.js │ ├── 110-lets-hoistingSpec.js │ ├── 120-let-and-switchSpec.js │ ├── 130-iefe-for-varSpec.js │ ├── 140-eliminate-iefe-with-letSpec.js │ ├── 150-const-reference-cannot-changeSpec.js │ └── desktop.ini ├── chapter02 │ ├── 010-function-statementSpec.js │ ├── 020-function-expressionSpec.js │ ├── 025-function-statement-vs-expressionSpec.js │ ├── 030-arrays-manipulation-with-function-expressionSpec.js │ ├── 040-fat-arrow-syntaxSpec.js │ ├── 050-arrow-parametersSpec.js │ ├── 060-arrow-block-bodySpec.js │ ├── 070-arrow-block-confusingSpec.js │ ├── 080-arrow-block-parenthesisSpec.js │ ├── 090-function-expression-invocation-patternsSpec.js │ ├── 120-arrow-expression-and-thisSpec.js │ ├── 125-arrow-functions-as-constructors-no-argumentsSpec.js │ ├── 130-arrays-manipulation-with-arrow-functionsSpec.js │ ├── 140-knowing-what-this-arrow-functionsSpec.js │ ├── 150-make-and-using-arrow-functionsSpec.js │ └── desktop.ini ├── chapter03 │ ├── 010-function-multi-aritySpec.js │ ├── 020-function-default-checksSpec.js │ ├── 030-function-default-argsSpec.js │ ├── 040-expression-default-paramSpec.js │ ├── 050-rectangleSpec.js │ ├── 060-triangleSpec.js │ ├── 080-default-before-requiredSpec.js │ ├── 090-using-argumentsSpec.js │ ├── 100-arguments-against-argumentsSpec.js │ ├── 110-rest-params-instead-of-argumentsSpec.js │ ├── 120-rest-params-lengthSpec.js │ └── desktop.ini ├── chapter04 │ ├── 010-convoluted-lookupSpec.js │ ├── 020-perimeter-applySpec.js │ ├── 030-perimeter-spreadSpec.js │ ├── 040-spread-console-logSpec.js │ ├── 050-spread-create-concatenate-arraysSpec.js │ ├── 060-spread-rest-togetherSpec.js │ ├── 065-object-api-defineProperties-enumerableSpec.js │ ├── 067-object-api-defineProperties-enumerableSpec.js │ ├── 068-object-assignSpec.js │ ├── 069-object-spreadSpec.js │ ├── 070-array-destructuringSpec.js │ ├── 080-array-destructuring-defaultsSpec.js │ ├── 090-array-destructuring-function-parameterSpec.js │ ├── 100-array-destructuring-restSpec.js │ ├── 110-recursive-orSpec.js │ ├── 120-array-nested-destructuringSpec.js │ ├── 121-multiple-returnsSpec.js │ ├── 125-destruct-rest-paramsSpec.js │ ├── 130-object-destructuringSpec.js │ ├── 140-object-destructuring-allSpec.js │ ├── 150-convoluted-lookup-with-destructuringSpec.js │ └── desktop.ini ├── chapter05 │ ├── 005-interpolationSpec.js │ ├── 010-simple-template-literalSpec.js │ ├── 020-nested-interpolationSpec.js │ ├── 030-escaping-literalsSpec.js │ ├── 040-static-vs-dynamicSpec.js │ ├── 050-reimplement-template-stringsSpec.js │ ├── 060-emmet-handlerSpec.js │ └── desktop.ini ├── chapter06 │ ├── 010-objects-keys-stringsSpec.js │ ├── 020-maps-construction-manipulationSpec.js │ ├── 030-maps-whole-manipulationSpec.js │ ├── 040-spreading-mapsSpec.js │ ├── 050-maps-from-other-mapsSpec.js │ ├── 055-no-literals-for-mapsSpec.js │ ├── 060-maps-to-from-jsonSpec.js │ ├── 070-maps-to-from-json-failSpec.js │ ├── 080-maps-hard-referencesSpec.js │ ├── 090-sets-construction-manipulationSpec.js │ ├── 100-sets-whole-manipulationSpec.js │ ├── 110-sets-from-other-setSpec.js │ ├── 120-use-for-weaksetsSpec.js │ └── desktop.ini ├── chapter07 │ ├── 010-object-literal-getters-settersSpec.js │ ├── 020-object-literal-computed-propertySpec.js │ ├── 025-revealing-module-patternSpec.js │ ├── 050-object-literal-method-shorthandSpec.js │ ├── 060-object-literal-inline-computed-propertySpec.js │ ├── 070-revealing-module-pattern-shorthandSpec.js │ ├── 080-trailing-comma-arrays-objectsSpec.js │ ├── 090-trailing-comma-functionsSpec.js │ └── desktop.ini ├── chapter08 │ ├── 020-method-hook-using-stringsSpec.js │ ├── 040-symbols-are-uniqueSpec.js │ ├── 050-overriding-object-keys-with-symbolsSpec.js │ ├── 070-method-hook-using-symbolsSpec.js │ ├── 080-switch-case-using-stringsSpec.js │ ├── 090-switch-case-using-symbolsSpec.js │ ├── 100-symbol-forSpec.js │ ├── 110-symbol-keyForSpec.js │ ├── 120-string-matchSpec.js │ ├── 130-symbol-matchSpec.js │ ├── 140-object-enumerate-keysSpec.js │ └── desktop.ini ├── chapter09 │ ├── 010-for-in-loop-arraysSpec.js │ ├── 020-es5-fibonacciSpec.js │ ├── 030-simple-iterableSpec.js │ ├── 035-for-of-loop-arraySpec.js │ ├── 040-loops-for-of-all-datastructuresSpec.js │ ├── 045-iterator-returnSpec.js │ ├── 050-simple-generatorSpec.js │ ├── 060-generator-fibonacciSpec.js │ ├── 070-simple-generator-pushSpec.js │ ├── 080-generator-returnSpec.js │ ├── 090-yield -generatorSpec.js │ └── desktop.ini ├── chapter10 │ ├── 010-basic-promiseSpec.js │ ├── 020-promisify-xhrSpec.js │ ├── 025-promisify-xhr-with-then-catchSpec.js │ ├── 030-promise-allSpec.js │ ├── 040-promise-raceSpec.js │ └── desktop.ini ├── chapter11 │ ├── 010-basic-classSpec.js │ ├── 015-basic-prototypal-inheritanceSpec.js │ ├── 020-classesSpec.js │ ├── 030-classes-prototypal-inheritanceSpec.js │ ├── 040-classes-static-methodsSpec.js │ └── desktop.ini ├── chapter12 │ ├── 010-iefe-for-varSpec.js │ ├── 020-named-inline-exportsSpec.js │ ├── 030-named-exportsSpec.js │ ├── 040-default-exportsSpec.js │ ├── 050-alias-exportsSpec.js │ ├── 060-named-importsSpec.js │ ├── 070-named-aliased-importSpec.js │ ├── 080-wildcard-importSpec.js │ ├── 090-aliasing-importsSpec.js │ ├── 100-default-importSpec.js │ ├── 110-default-with-aliased-importsSpec.js │ └── desktop.ini ├── chapter13 │ ├── 010-array-prototype-equalsSpec.js │ ├── 020-intercept-methodSpec.js │ ├── 030-simple-proxySpec.js │ ├── 040-intercept-method-callsSpec.js │ ├── 050-array-prototype-equals-using-proxySpec.js │ ├── 060-singleton-using-proxiesSpec.js │ ├── 080-xml-builderSpec.js │ └── desktop.ini ├── chapter14 │ ├── 010-simple-math-imperativelySpec.js │ ├── 020-simple-math-using-promisesSpec.js │ ├── 025-sync-async-conditionalSpec.js │ ├── 030-simple-asyncSpec.js │ ├── 040-simple-async-awaitSpec.js │ ├── 050-simple-math-using-async-awaitSpec.js │ ├── 055-sync-async-conditional-againSpec.js │ ├── 060-fetch-with-async-awaitSpec.js │ ├── 065-error-trappingSpec.js │ ├── 070-too-much-waitingSpec.js │ └── desktop.ini ├── chapter15 │ ├── 010-asynchronous-iterationSpec.js │ ├── 020-asynchronous-generator-async-awaitSpec.js │ ├── 030-simple-sync-generatorSpec.js │ ├── 040-simple-async-iterableSpec.js │ ├── 050-simple-async-iterable-for-async-awaitSpec.js │ ├── 060-simple-async-iterable-rejectSpec.js │ ├── 070-simple-async-iterable-try-catchSpec.js │ ├── 080-for-await-of-sync-iterableSpec.js │ ├── 090-aync-generatorSpec.js │ └── desktop.ini ├── desktop.ini └── mocha.opts ├── tools ├── .eslintrc ├── build.js └── desktop.ini └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | # Change these settings to your own preference 9 | indent_style = space 10 | indent_size = 2 11 | 12 | # We recommend you to keep these unchanged 13 | end_of_line = lf 14 | charset = utf-8 15 | trim_trailing_whitespace = true 16 | insert_final_newline = true 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Automatically normalize line endings for all text-based files 2 | # http://git-scm.com/docs/gitattributes#_end_of_line_conversion 3 | * text=auto 4 | 5 | # For the following file types, normalize line endings to LF on 6 | # checkin and prevent conversion to CRLF when they are checked out 7 | # (this is required in order to prevent newline related issues like, 8 | # for example, after the build script is run) 9 | .* text eol=lf 10 | *.css text eol=lf 11 | *.ejs text eol=lf 12 | *.js text eol=lf 13 | *.md text eol=lf 14 | *.txt text eol=lf 15 | *.json text eol=lf 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Include your project-specific ignores in this file 2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files 3 | 4 | .nyc_output 5 | coverage 6 | dist 7 | docs/dist 8 | node_modules 9 | npm-debug.log 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '10' 5 | - '8' 6 | script: 7 | - npm run lint 8 | - npm run test:cover 9 | after_success: 10 | - npm run coveralls 11 | -------------------------------------------------------------------------------- /9781484253939.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/javascript-next/1a2c413942b640917c2d3b145c44d1a5d11f109f/9781484253939.jpg -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *Book Title* 2 | 3 | On **page xx** [Summary of error]: 4 | 5 | Details of error here. Highlight key pieces in **bold**. 6 | 7 | *** 8 | 9 | On **page xx** [Summary of error]: 10 | 11 | Details of error here. Highlight key pieces in **bold**. 12 | 13 | *** -------------------------------------------------------------------------------- /src/chapter01/030-var-overwriting.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-redeclare, no-var, block-scoped-var */ 2 | /* eslint-disable no-constant-condition, vars-on-top, no-console */ 3 | // tag::insidious[] 4 | function insidious() { 5 | var functionScoped = 'Outer declaration'; // <1> 6 | if (true) { 7 | var functionScoped = 'Inner declaration'; // <2> 8 | } 9 | console.log(functionScoped); // <3> 10 | return functionScoped; 11 | } 12 | // prints 'Inner declaration' 13 | insidious(); 14 | // end::insidious[] 15 | export default insidious; 16 | -------------------------------------------------------------------------------- /src/chapter01/031-simulate-dom.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-var, vars-on-top, no-plusplus, prefer-template */ 2 | /* eslint-disable no-loop-func, func-names, no-console */ 3 | 4 | // tag::simulateDom[] 5 | function simulateDom() { 6 | var pseudoDom = { 7 | button1: {}, 8 | button2: {}, 9 | button3: {}, 10 | }; // <1> 11 | 12 | for (var i = 1; i <= 3; i++) { 13 | var element = pseudoDom['button' + i]; 14 | element.click = function () { 15 | return 'Item ' + i + ' is clicked.'; // <2> 16 | }; 17 | } 18 | 19 | console.log(pseudoDom.button1.click()); 20 | console.log(pseudoDom.button2.click()); 21 | console.log(pseudoDom.button3.click()); // <3> 22 | return pseudoDom; 23 | } 24 | // prints 'Item 4 is clicked.' 3 times 25 | simulateDom(); 26 | // end::simulateDom[] 27 | 28 | export default simulateDom; 29 | -------------------------------------------------------------------------------- /src/chapter01/090-let-variables.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars, no-constant-condition, prefer-const */ 2 | 3 | // tag::letFunction[] 4 | function letFunction() { 5 | // console.log('Before defining block', scopedLet); // <1> 6 | if (true) { 7 | let scopedLet = 'I am scoped within a block!'; // <2> 8 | } 9 | // console.log('After defining block', scopedVar); // <3> 10 | } 11 | 12 | // invoke it 13 | letFunction(); 14 | // end::letFunction[] 15 | export default letFunction; 16 | -------------------------------------------------------------------------------- /src/chapter01/100-simulate-dom-with-let.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-plusplus, prefer-template */ 2 | /* eslint-disable no-loop-func, func-names */ 3 | /* eslint-disable no-unused-vars, prefer-const, no-console */ 4 | // tag::simulateDom[] 5 | function simulateDom() { 6 | let pseudoDom = { 7 | button1: {}, 8 | button2: {}, 9 | button3: {}, 10 | }; 11 | 12 | for (let i = 1; i <= 3; i++) { // <1> 13 | let element = pseudoDom['button' + i]; 14 | element.click = function () { 15 | return 'Item ' + i + ' is clicked.'; // <2> 16 | }; 17 | } 18 | 19 | console.log(pseudoDom.button1.click()); 20 | console.log(pseudoDom.button2.click()); 21 | console.log(pseudoDom.button3.click()); // <3> 22 | return pseudoDom; 23 | } 24 | // prints 'Item 1 is clicked.', 'Item 2 is clicked.', 'Item 3 is clicked.' 25 | simulateDom(); 26 | // end::simulateDom[] 27 | 28 | export default simulateDom; 29 | -------------------------------------------------------------------------------- /src/chapter01/110-let-hoisted.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-mutable-exports, func-names, quotes */ 2 | /* eslint-disable no-var, no-console, no-use-before-define */ 3 | // tag::hoisting[] 4 | var foo; 5 | { // <1> 6 | foo = function () { 7 | console.log('I am', bar); // <2> 8 | }; 9 | 10 | let bar = 'Bar'; // <3> 11 | // prints 'I am Bar' 12 | foo(); // <4> 13 | } 14 | // end::hoisting[] 15 | export default foo; 16 | -------------------------------------------------------------------------------- /src/chapter01/120-let-and-switch.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-case-declarations, no-redeclare, no-undef, no-unused-vars, semi */ 2 | // tag::let-and-switch[] 3 | function determineFavoriteDrink(profession) { 4 | switch (profession) { 5 | case 'Programmer': 6 | let drink = 'coffee'; // <1> 7 | break 8 | case 'Yoga instructor': 9 | let drink = 'tea'; // <2> 10 | break; 11 | default: 12 | let drink = 'water'; // <3> 13 | break; 14 | } 15 | return drink; 16 | } 17 | // results in 'SyntaxError' 18 | console.log(determineFavoriteDrink('Programmer')); 19 | // end::let-and-switch[] 20 | -------------------------------------------------------------------------------- /src/chapter01/130-iefe-for-var.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-mutable-exports, no-plusplus, object-shorthand */ 2 | /* eslint-disable no-var, no-console */ 3 | // tag::iefe[] 4 | var counter = (function createCounter() { // <1> 5 | var steps = 0; // <2> 6 | function increment() { 7 | steps++; 8 | } 9 | function getCount() { 10 | return steps; 11 | } 12 | 13 | return { 14 | increment: increment, 15 | getCount: getCount, 16 | }; // <3> 17 | }()); 18 | // use it 19 | // console.log(steps); // <4> 20 | counter.increment(); // <5> 21 | console.assert(counter.getCount() === 1); // <6> 22 | // end::iefe[] 23 | export default counter; 24 | -------------------------------------------------------------------------------- /src/chapter01/140-eliminate-iefe-with-let.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-mutable-exports, no-plusplus, object-shorthand */ 2 | /* eslint-disable prefer-const, func-names, no-console, prefer-const */ 3 | /* eslint-disable no-console */ 4 | // tag::block-scope[] 5 | let counter; 6 | { // <1> 7 | let steps = 0; // <2> 8 | let increment = function () { // <3> 9 | console.log('increment'); 10 | steps++; 11 | }; 12 | let getCount = function () { 13 | return steps; 14 | }; 15 | 16 | counter = { 17 | increment: increment, 18 | getCount: getCount, 19 | }; // <4> 20 | } 21 | // use it 22 | // console.log(steps); // <5> 23 | counter.increment(); // <6> 24 | console.assert(counter.getCount() === 1); // <7> 25 | // end::block-scope[] 26 | export default counter; 27 | -------------------------------------------------------------------------------- /src/chapter01/150-const-reference-cannot-change.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::const-references[] 3 | const VALUE_REFERENCE = 'This cannot be re-assigned'; // <1> 4 | const ARRAY_REFERENCE = ['I', 'am', 'mutable']; // <2> 5 | 6 | // attempt re-assignment 7 | // VALUE_REFERENCE = false 8 | // ARRAY_REFERENCE = {} // <3> 9 | 10 | // Mutate the array object 11 | ARRAY_REFERENCE.push('!'); // <4> 12 | // prints [ 'I', 'am', 'mutable', '!' ] 13 | console.log(ARRAY_REFERENCE); 14 | // end::const-references[] 15 | export { 16 | VALUE_REFERENCE, 17 | ARRAY_REFERENCE, 18 | }; 19 | -------------------------------------------------------------------------------- /src/chapter01/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter02/010-function-statement.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::identity[] 3 | function identity(n) { // <1> 4 | return n; 5 | } 6 | // invoke it 7 | console.assert(identity(42) === 42); 8 | 9 | // inspect it 10 | console.assert((typeof identity) === 'function'); // <2> 11 | console.assert(identity.name === 'identity'); // <3> 12 | 13 | // end::identity[] 14 | export default identity; 15 | -------------------------------------------------------------------------------- /src/chapter02/020-function-expression.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names */ 2 | /* eslint-disable no-console */ 3 | // tag::identity[] 4 | const identity = function (n) { // <1> 5 | return n; 6 | }; 7 | 8 | // invoke it 9 | console.assert(identity(42) === 42); 10 | 11 | // inspect it 12 | console.assert((typeof identity) === 'function'); // <2> 13 | console.assert(identity.name === 'identity'); // <3> 14 | // end::identity[] 15 | export default identity; 16 | -------------------------------------------------------------------------------- /src/chapter02/025-function-statement-vs-expression.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable func-names, no-use-before-define */ 3 | // tag::025-function-statement-vs-expression[] 4 | // invoke it before defining it 5 | fnStatement(); // <1> 6 | function fnStatement() { // <2> 7 | console.log('I am a function statement'); 8 | } 9 | // invoke it 10 | fnStatement(); 11 | 12 | // fnExpression(); // <3> 13 | const fnExpression = function () { // <4> 14 | console.log('I am a function expression'); 15 | }; 16 | // invoke it 17 | fnExpression(); 18 | 19 | // end::025-function-statement-vs-expression[] 20 | export { 21 | fnStatement, 22 | fnExpression, 23 | }; 24 | -------------------------------------------------------------------------------- /src/chapter02/030-arrays-manipulation-with-function-expression.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names, prefer-arrow-callback, no-param-reassign, indent */ 2 | /* eslint-disable indent, no-console */ 3 | 4 | const arrayManipulation = function () { 5 | // tag::arrayManipulation[] 6 | const nums = [1, 2, 3, 4, 5]; 7 | 8 | const result = nums 9 | .map(function (n) { 10 | return n * 3; // <1> 11 | }) 12 | .filter(function (n) { 13 | return (n % 2) === 0; // <2> 14 | }) 15 | .reduce(function (acc, n) { 16 | return acc + n; // <3> 17 | }, 0); 18 | // end::arrayManipulation[] 19 | return result; 20 | }; 21 | 22 | console.assert(arrayManipulation() === 18); 23 | export default arrayManipulation; 24 | -------------------------------------------------------------------------------- /src/chapter02/040-fat-arrow-syntax.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::doubleIt[] 3 | const doubleIt = n => n * 2; 4 | 5 | // invoke it 6 | console.assert(doubleIt(8) === 16); 7 | 8 | // end::doubleIt[] 9 | export default doubleIt; 10 | -------------------------------------------------------------------------------- /src/chapter02/050-arrow-parameters.js: -------------------------------------------------------------------------------- 1 | // tag::parameterList[] 2 | 3 | const noop = () => {}; // <1> 4 | const identity = n => n; // <2> 5 | const get = (obj, k) => obj[k]; // <3> 6 | 7 | // end::parameterList[] 8 | export { 9 | noop, 10 | identity, 11 | get, 12 | }; 13 | -------------------------------------------------------------------------------- /src/chapter02/060-arrow-block-body.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::blockBody[] 3 | const reducer = (acc, n) => { // <1> 4 | acc.push(n); 5 | return acc; // <2> 6 | }; 7 | 8 | // prints '[ 2, 3, 1 ]' 9 | console.log(reducer([2, 3], 1)); 10 | 11 | // end::blockBody[] 12 | export default reducer; 13 | -------------------------------------------------------------------------------- /src/chapter02/070-arrow-block-confusing.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-labels, no-unused-labels */ 2 | /* eslint-disable no-unused-expressions, no-console */ 3 | // For some reason eslint complains about missing semi here 4 | /* eslint-disable semi */ 5 | 6 | // tag::confusingBody[] 7 | const confuser = () => { profession: 'JS Ninja' }; 8 | // invoke it 9 | console.log(confuser()); 10 | 11 | // end::confusingBody[] 12 | export default confuser; 13 | -------------------------------------------------------------------------------- /src/chapter02/080-arrow-block-parenthesis.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, arrow-body-style */ 2 | // tag::confusingBody[] 3 | 4 | const confuserOne = () => ({ profession: 'JS Ninja' }); 5 | // prints '{ profession: 'JS Ninja' }' 6 | console.log(confuserOne()); 7 | 8 | // alternatively 9 | const confuserTwo = () => { 10 | return { profession: 'JS Ninja' }; 11 | }; 12 | // prints '{ profession: 'JS Ninja' }' 13 | console.log(confuserTwo()); 14 | 15 | // end::confusingBody[] 16 | export { 17 | confuserOne, 18 | confuserTwo, 19 | }; 20 | -------------------------------------------------------------------------------- /src/chapter02/090-function-expression-invocation-patterns.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names, lines-around-directive, strict */ 2 | /* eslint-disable no-var, no-console, vars-on-top */ 3 | 4 | // tag::invocation-patterns[] 5 | 'use strict'; 6 | 7 | const returnsThis = function () { 8 | return this; 9 | }; 10 | 11 | var obj1 = { 12 | name: 'obj1', 13 | method: returnsThis, // <1> 14 | }; 15 | 16 | console.assert(obj1.method() === obj1); // <2> 17 | 18 | var obj2 = { 19 | name: 'obj2', 20 | }; 21 | 22 | console.assert(returnsThis.apply(obj2) === obj2); // <3> 23 | console.assert(returnsThis() === undefined); // <4> 24 | // end::invocation-patterns[] 25 | export default returnsThis; 26 | -------------------------------------------------------------------------------- /src/chapter02/120-arrow-expression-and-this.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names, lines-around-directive, strict */ 2 | /* eslint-disable no-var, no-console, vars-on-top */ 3 | 4 | // tag::arrow-lexical-binding[] 5 | 'use strict'; 6 | 7 | const GLOBAL_OBJECT = this; // <1> 8 | const returnMe = () => this; // <2> 9 | 10 | var obj1 = { 11 | name: 'obj1', 12 | method: returnMe, 13 | }; 14 | console.assert(obj1.method() === GLOBAL_OBJECT); // <3> 15 | 16 | var obj2 = { 17 | name: 'obj2', 18 | }; 19 | console.assert(returnMe.apply(obj2) === GLOBAL_OBJECT); // <4> 20 | console.assert(returnMe() === GLOBAL_OBJECT); // <5> 21 | // end::arrow-lexical-binding[] 22 | export { 23 | GLOBAL_OBJECT, 24 | returnMe, 25 | }; 26 | -------------------------------------------------------------------------------- /src/chapter02/130-arrays-manipulation-with-arrow-functions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names, prefer-arrow-callback, no-param-reassign */ 2 | /* eslint-disable space-before-function-paren, indent, no-console */ 3 | 4 | const arrayManipulation = function() { 5 | // tag::arrayManipulation[] 6 | const nums = [1, 2, 3, 4, 5]; 7 | 8 | const result = nums 9 | .map(n => n * 3) // <1> 10 | .filter(n => (n % 2) === 0) // <2> 11 | .reduce((acc, n) => acc + n, 0); // <3> 12 | // end::arrayManipulation[] 13 | return result; 14 | }; 15 | 16 | console.assert(arrayManipulation() === 18); 17 | export default arrayManipulation; 18 | -------------------------------------------------------------------------------- /src/chapter02/140-knowing-what-this-arrow-functions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable object-shorthand, func-names, prefer-rest-params */ 2 | /* eslint-disable no-console */ 3 | 4 | // tag::knowing-this[] 5 | const neo = { 6 | friends: [ 7 | 'Morpheus', 8 | 'Brian', 9 | 'Switch', 10 | ], 11 | addFriends: function () { 12 | const args = Array.prototype.slice.call(arguments); 13 | args.forEach(f => this.friends.push(f)); // <2> 14 | }, 15 | }; 16 | // invoke addFriends 17 | neo.addFriends('Niobe', 'Tank'); // <1> 18 | // prints '[ 'Morpheus', 'Brian', 'Switch', 'Niobe', 'Tank' ]' 19 | console.log(neo.friends); 20 | // end::knowing-this[] 21 | export default neo; 22 | -------------------------------------------------------------------------------- /src/chapter02/150-make-and-using-arrow-functions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names, prefer-arrow-callback, no-param-reassign */ 2 | /* eslint-disable no-console */ 3 | 4 | // tag::make-and-function[] 5 | const and = (a, b) => arg => a(arg) && b(arg); // <1> 6 | 7 | const gt10 = n => n > 10; // <2> 8 | const even = n => n % 2 === 0; // <3> 9 | 10 | const evenAndGt10 = and(gt10, even); // <4> 11 | 12 | console.assert(evenAndGt10(15) === false); 13 | console.assert(evenAndGt10(22) === true); 14 | // end::make-and-function[] 15 | export default and; 16 | -------------------------------------------------------------------------------- /src/chapter02/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter03/010-function-multi-arity.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable prefer-template, guard-for-in, no-restricted-syntax */ 3 | /* eslint-disable space-in-parens, spaced-comment, prefer-rest-params */ 4 | 5 | // tag::multi-arity[] 6 | const sayHello = name => 'Hello ' + name; 7 | 8 | const buildUrl = (site, protocol) => protocol + '://' + site; 9 | 10 | function add( /**args*/ ) { // <1> 11 | let result = 0; 12 | for (const i in arguments) { 13 | result += arguments[i]; 14 | } 15 | return result; 16 | } 17 | 18 | console.assert(sayHello.length === 1); 19 | console.assert(buildUrl.length === 2); 20 | console.assert(add.length === 0); 21 | 22 | // prints 'Hello undefined' 23 | console.log(sayHello()); // <2> 24 | // prints 'https://jsrocks.com' 25 | console.log(buildUrl('jsrocks.com', 'https', 'non-required argument')); // <3> 26 | // prints 42 27 | console.log(add(12, 22, 8)); // <4> 28 | // end::multi-arity[] 29 | export { 30 | add, 31 | sayHello, 32 | buildUrl, 33 | }; 34 | -------------------------------------------------------------------------------- /src/chapter03/020-function-default-checks.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-template */ 2 | 3 | // tag::default-checks[] 4 | 5 | /** 6 | * Builds a url 7 | * 8 | * @param {site} the url (required) 9 | * @param {protocol} can be http or https (optional) - defaults to http 10 | * @returns {string} 11 | */ 12 | const buildUrl = (site, protocol) => { 13 | if (!site) { // <1> 14 | throw new Error('site is required'); 15 | } 16 | const p = protocol || 'http'; // <2> 17 | return p + '://' + site; 18 | }; 19 | 20 | // end::default-checks[] 21 | export default buildUrl; 22 | -------------------------------------------------------------------------------- /src/chapter03/030-function-default-args.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-template */ 2 | 3 | // tag::default-args[] 4 | const buildUrl = (site, protocol = 'http') => { 5 | if (!site) { 6 | throw new Error('site is required'); 7 | } 8 | return protocol + '://' + site; 9 | }; 10 | 11 | // end::default-args[] 12 | export default buildUrl; 13 | -------------------------------------------------------------------------------- /src/chapter03/040-expression-default-param.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | 3 | // tag::default-function-expression[] 4 | const getDefaultConn = () => { 5 | // look up ENV config 6 | // return appropriate connection 7 | // as a default assume localhost 8 | return { 9 | host: 'localhost', 10 | user: 'me', 11 | password: 'secret', 12 | database: 'my_db', 13 | }; 14 | }; 15 | 16 | const query = (sql, conn = getDefaultConn()) => { 17 | // use connection string and sql here to query db 18 | // conn.connect(); 19 | // conn.query(sql); 20 | // conn.close(); 21 | return conn; 22 | }; 23 | // end::default-function-expression[] 24 | export { 25 | getDefaultConn, 26 | query, 27 | }; 28 | -------------------------------------------------------------------------------- /src/chapter03/050-rectangle.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::rectangle[] 3 | const rectangle = (x, y = x) => [x, y]; // <1> 4 | 5 | // prints '[ 2, 2 ]' 6 | console.log(rectangle(2)); // <2> 7 | // prints '[ 5, 12 ]' 8 | console.log(rectangle(5, 12)); // <3> 9 | 10 | // end::rectangle[] 11 | export default rectangle; 12 | -------------------------------------------------------------------------------- /src/chapter03/060-triangle.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::triangle[] 3 | const triangle = (a, b = a, c = Math.hypot(a, b)) => [a, b, c]; 4 | 5 | // prints '[ 6, 4, 7.211102550927979 ]' 6 | console.log(triangle(6, 4)); 7 | // prints '[ 10, 10, 14.142135623730951 ]' 8 | console.log(triangle(10)); 9 | 10 | // end::triangle[] 11 | export default triangle; 12 | -------------------------------------------------------------------------------- /src/chapter03/080-default-before-required.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::default-before-required[] 3 | 4 | const filter = (coll = [], predFn) => coll.filter(predFn); 5 | 6 | // prints '[ 30 ]' 7 | console.log(filter([10, 20, 30], n => n > 25)); 8 | // end::default-before-required[] 9 | 10 | export default filter; 11 | -------------------------------------------------------------------------------- /src/chapter03/090-using-arguments.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable guard-for-in, no-restricted-syntax */ 2 | /* eslint-disable space-in-parens, spaced-comment, prefer-rest-params */ 3 | 4 | // tag::using-arguments[] 5 | function add( /**args*/ ) { 6 | let result = 0; 7 | for (const i in arguments) { 8 | result += arguments[i]; 9 | } 10 | return result; 11 | } 12 | // prints '20' 13 | console.log(add(2, 3, 5, 10)); 14 | // end::using-arguments[] 15 | export default add; 16 | -------------------------------------------------------------------------------- /src/chapter03/120-rest-params-length.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-unused-vars */ 3 | 4 | // tag::rest-params-length[] 5 | function fnExpression(a, b, ...c) { 6 | console.log(arguments.length); 7 | } 8 | 9 | const fnArrow = (a, b, ...c) => { 10 | // do not get an arguments object 11 | }; 12 | 13 | console.assert(fnExpression.length === 2); // <1> 14 | console.assert(fnArrow.length === 2); // <2> 15 | 16 | // prints '6' 17 | fnExpression(1, 2, 3, 4, 5, 6); // <3> 18 | // end::rest-params-length[] 19 | export { 20 | fnExpression, 21 | fnArrow, 22 | }; 23 | -------------------------------------------------------------------------------- /src/chapter03/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter04/010-convoluted-lookup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable prefer-template, prefer-destructuring */ 3 | const convolutedLookup = () => { 4 | // tag::convoluted-lookup[] 5 | const user = { 6 | name: 'douglas', 7 | profession: 'developer', 8 | address: { 9 | street1: '1 Ad Infinitum Drive', 10 | street2: '', 11 | city: 'Cupertino', 12 | state: 'CA', 13 | zip: [ 14 | '95014', 15 | '1234', 16 | ], 17 | }, 18 | }; 19 | 20 | const zipCode = user.address.zip[0] + '-' + user.address.zip[1]; // <1> 21 | console.assert(zipCode === '95014-1234'); 22 | 23 | // refactored version 24 | const zip = user.address.zip; // <2> 25 | const code = zip[0]; // <3> 26 | const extended = zip[1]; 27 | const final = code + '-' + extended; 28 | console.assert(final === '95014-1234'); 29 | 30 | // end::convoluted-lookup[] 31 | return [zipCode, final]; 32 | }; 33 | 34 | export default convolutedLookup; 35 | -------------------------------------------------------------------------------- /src/chapter04/020-perimeter-apply.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::020-perimeter-apply[] 3 | const perimeter = (a, b, c) => a + b + c; 4 | 5 | const sides = [9, 8, 3]; // <1> 6 | 7 | // prints 20 8 | console.log(perimeter(sides[0], sides[1], sides[2])); // <2> 9 | // end::020-perimeter-apply[] 10 | export default perimeter; 11 | -------------------------------------------------------------------------------- /src/chapter04/030-perimeter-spread.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::030-perimeter-spread[] 3 | const perimeter = (a, b, c) => a + b + c; 4 | 5 | const sides = [9, 8, 3]; // <1> 6 | 7 | // prints 20 8 | console.log(perimeter(...sides)); // <2> 9 | // end::030-perimeter-spread[] 10 | export default perimeter; 11 | -------------------------------------------------------------------------------- /src/chapter04/040-spread-console-log.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable guard-for-in, no-restricted-syntax, eqeqeq */ 3 | 4 | const printIt = () => { 5 | // tag::spread-console-log[] 6 | const arr = [12, -3, 15, 44, 15, 36]; // <1> 7 | 8 | // prints '[ 12, -3, 15, 44, 15, 36 ]' 9 | console.log(arr); // <2> 10 | // prints '12 -3 15 44 15 36' 11 | console.log(...arr); // <3> 12 | 13 | // to get the same result as we did with the spread operator 14 | let temp = ''; 15 | for (const i in arr) { 16 | temp += arr[i]; 17 | if (i != (arr.length - 1)) { 18 | temp += ' '; 19 | } 20 | } 21 | console.assert(temp === '12 -3 15 44 15 36'); // <4> 22 | 23 | // end::spread-console-log[] 24 | return [arr, temp]; 25 | }; 26 | export default printIt; 27 | -------------------------------------------------------------------------------- /src/chapter04/050-spread-create-concatenate-arrays.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const createAndConcatenate = () => { 3 | // tag::spread-create-concatenate-arrays[] 4 | const one = [12, -3, 15]; 5 | const otherOne = [...one]; // <1> 6 | const two = [44, 15, 36]; // <2> 7 | 8 | // mutation 9 | one.push(...two); // <3> 10 | // prints '[ 12, -3, 15, 44, 15, 36 ]' 11 | console.log(one); 12 | 13 | // alternatively inline the concatenation 14 | const concatenated = [12, -3, 15, ...two]; // <4> 15 | // prints '[ 12, -3, 15, 44, 15, 36 ]' 16 | console.log(concatenated); 17 | 18 | // create a new array 19 | const newArr = [...otherOne, ...two]; // <5> 20 | // prints '[ 12, -3, 15, 44, 15, 36 ]' 21 | console.log(newArr); 22 | 23 | // end::spread-create-concatenate-arrays[] 24 | return [one, concatenated, newArr]; 25 | }; 26 | export default createAndConcatenate; 27 | -------------------------------------------------------------------------------- /src/chapter04/060-spread-rest-together.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable arrow-body-style */ 3 | // tag::spread-and-rest[] 4 | const onlyRest = (teacher, ...students) => { 5 | return [teacher, students.sort()]; // <1> 6 | }; 7 | 8 | const restAndSpread = (teacher, ...students) => { 9 | return [teacher, ...students.sort()]; // <2> 10 | }; 11 | 12 | // prints '[ 'Ada', [ 'Carol', 'Grace', 'Mary' ] ]' 13 | console.log(onlyRest('Ada', 'Mary', 'Carol', 'Grace')); 14 | // prints '[ 'Ada', 'Carol', 'Grace', 'Mary' ]' 15 | console.log(restAndSpread('Ada', 'Mary', 'Carol', 'Grace')); 16 | // end::spread-and-rest[] 17 | export { 18 | onlyRest, 19 | restAndSpread, 20 | }; 21 | -------------------------------------------------------------------------------- /src/chapter04/065-object-api-defineProperties-enumerable.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::065-object-api-defineProperties-enumerable[] 3 | const michelle = {}; 4 | Object.defineProperties(michelle, { // <1> 5 | name: { 6 | value: 'Michelle', // <2> 7 | }, 8 | hobby: { 9 | value: 'Gardening', 10 | }, 11 | }); 12 | 13 | // prints 'Michelle' 14 | console.log(michelle.name); 15 | // prints 'Gardening' 16 | console.log(michelle.hobby); 17 | // end::065-object-api-defineProperties-enumerable[] 18 | export default michelle; 19 | -------------------------------------------------------------------------------- /src/chapter04/067-object-api-defineProperties-enumerable.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, no-restricted-syntax */ 2 | // tag::067-object-api-defineProperties-enumerable[] 3 | const michelle = {}; 4 | Object.defineProperties(michelle, { 5 | name: { 6 | value: 'Michelle', 7 | enumerable: true, // <1> 8 | }, 9 | hobby: { 10 | value: 'Gardening', // <2> 11 | }, 12 | }); 13 | 14 | for (const k in michelle) { 15 | if (Object.prototype.hasOwnProperty.call(michelle, k)) { 16 | // only prints 'name' 17 | console.log(k); // <3> 18 | } 19 | } 20 | // end::067-object-api-defineProperties-enumerable[] 21 | export default michelle; 22 | -------------------------------------------------------------------------------- /src/chapter04/068-object-assign.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::068-object-assign[] 3 | const michelle = { // <1> 4 | name: 'Michelle', 5 | hobby: 'Gardening', 6 | }; 7 | 8 | const rachael = Object.assign({}, michelle, { // <2> 9 | name: 'Rachael', 10 | profession: 'Auditor', 11 | }); 12 | 13 | // prints '{ name: 'Rachael', hobby: 'Gardening', profession: 'Auditor' }' 14 | console.log(rachael); 15 | 16 | // end::068-object-assign[] 17 | export default rachael; 18 | -------------------------------------------------------------------------------- /src/chapter04/069-object-spread.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::069-object-spread[] 3 | const michelle = { 4 | name: 'Michelle', 5 | hobby: 'Gardening', 6 | }; 7 | 8 | const rachael = { 9 | ...michelle, // <1> 10 | ...{ 11 | name: 'Rachael', 12 | profession: 'Auditor', 13 | }, 14 | }; 15 | 16 | // prints '{ name: 'Rachael', hobby: 'Gardening', profession: 'Auditor' }' 17 | console.log(rachael); 18 | 19 | // end::069-object-spread[] 20 | export default rachael; 21 | -------------------------------------------------------------------------------- /src/chapter04/070-array-destructuring.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::array-destructuring[] 3 | 4 | const rgba = [239, 15, 255, 0.9]; // <1> 5 | const [r, g, b, a, nonExistent] = rgba; // <2> 6 | console.assert(r === 239); 7 | console.assert(g === 15); 8 | console.assert(b === 255); 9 | console.assert(a === 0.9); 10 | console.assert(nonExistent === undefined); // <3> 11 | 12 | const [, , blue] = rgba; // <4> 13 | const blueAgain = rgba[2]; 14 | 15 | console.assert(blue === b); 16 | console.assert(blueAgain === b); 17 | 18 | // end::array-destructuring[] 19 | export { 20 | r, 21 | g, 22 | b, 23 | a, 24 | nonExistent, 25 | blue, 26 | blueAgain, 27 | }; 28 | -------------------------------------------------------------------------------- /src/chapter04/080-array-destructuring-defaults.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, indent */ 2 | // tag::array-destructuring-defaults[] 3 | const quadrilateral = [10, 15, 10, 15]; // <1> 4 | const [q1 = 10, 5 | q2 = 20, 6 | q3 = q1, 7 | q4 = q2] = quadrilateral; // <2> 8 | 9 | console.assert(q1 === 10); 10 | console.assert(q2 === 15); 11 | console.assert(q3 === 10); 12 | console.assert(q4 === 15); 13 | 14 | const [sq1 = 10, 15 | sq2 = sq1, 16 | sq3 = sq1, 17 | sq4 = sq1] = []; // <3> 18 | 19 | console.assert(sq1 === 10); 20 | console.assert(sq2 === 10); 21 | console.assert(sq3 === 10); 22 | console.assert(sq4 === 10); 23 | 24 | // end::array-destructuring-defaults[] 25 | export { 26 | q1, 27 | q2, 28 | q3, 29 | q4, 30 | sq1, 31 | sq2, 32 | sq3, 33 | sq4, 34 | }; 35 | -------------------------------------------------------------------------------- /src/chapter04/090-array-destructuring-function-parameter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, indent */ 2 | /* eslint-disable arrow-body-style */ 3 | 4 | // tag::array-destructuring-defaults[] 5 | const perimeter = ([s1 = 10, 6 | s2 = s1, 7 | s3 = s1, 8 | s4 = s2] = []) => { // <1> 9 | return s1 + s2 + s3 + s4; 10 | }; 11 | 12 | console.assert(perimeter() === 40); // <2> 13 | console.assert(perimeter([]) === 40); // <3> 14 | console.assert(perimeter([15]) === 60); // <4> 15 | console.assert(perimeter([15, 20]) === 70); // <5> 16 | console.assert(perimeter([15, 20, 18, 23]) === 76); // <6> 17 | // end::array-destructuring-defaults[] 18 | 19 | export default perimeter; 20 | -------------------------------------------------------------------------------- /src/chapter04/100-array-destructuring-rest.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::array-destructuring-rest[] 3 | const movies = ['Momento', 'Batman Begins', 'The Dark Knight']; 4 | 5 | const [first, ...rest] = movies; // <1> 6 | console.assert(first === 'Momento'); 7 | console.assert(Array.isArray(rest)); 8 | 9 | const [head, ...tail] = rest; // <2> 10 | console.assert(head === 'Batman Begins'); 11 | console.assert(Array.isArray(tail)); 12 | 13 | // end::array-destructuring-rest[] 14 | 15 | export { 16 | movies, 17 | first, 18 | rest, 19 | head, 20 | tail, 21 | }; 22 | -------------------------------------------------------------------------------- /src/chapter04/110-recursive-or.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::recursive-or[] 3 | 4 | const or = (...args) => { 5 | if (args.length === 0) return null; 6 | if (args.length === 1) return args[0]; // <1> 7 | const [first, ...rest] = args; // <2> 8 | return first || or(...rest); // <3> 9 | }; 10 | 11 | console.assert(or(null, undefined, true, false, '1')); 12 | console.assert(!or(null, undefined, false)); 13 | // end::recursive-or[] 14 | 15 | export default or; 16 | -------------------------------------------------------------------------------- /src/chapter04/120-array-nested-destructuring.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::nested-array-destructuring[] 3 | const ticTacToe = [ 4 | ['x', 'o', 'x'], 5 | ['o', 'x', 'o'], 6 | ['x', 'o', 'x'], 7 | ]; 8 | 9 | const [ 10 | [cell01] = [], 11 | [, cell11] = [], 12 | [, , cell22] = [], // <1> 13 | ] = ticTacToe; // <2> 14 | 15 | console.assert(cell01 === 'x'); 16 | console.assert(cell11 === 'x'); 17 | console.assert(cell22 === 'x'); 18 | // end::nested-array-destructuring[] 19 | 20 | export { 21 | ticTacToe, 22 | cell01, 23 | cell11, 24 | cell22, 25 | }; 26 | -------------------------------------------------------------------------------- /src/chapter04/121-multiple-returns.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::multiple-returns[] 3 | const distanceAndSlope = ([x1, y1], [x2, y2]) => { 4 | const distance = Math.hypot(x2 - x1, y2 - y1); 5 | const slope = (y2 - y1) / (x2 - x1); 6 | return [distance, slope]; // <1> 7 | }; 8 | 9 | const [dist, slope] = distanceAndSlope([4, 3], [10, 12]); // <2> 10 | 11 | console.assert(Number.parseFloat(dist.toFixed(2)) === 10.82); 12 | console.assert(slope === 1.5); 13 | // end::multiple-returns[] 14 | 15 | export default distanceAndSlope; 16 | -------------------------------------------------------------------------------- /src/chapter04/125-destruct-rest-params.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::destruct-rest-params[] 3 | const flatten = ([first, ...rest]) => { 4 | if (first === undefined) return []; // <1> 5 | return !Array.isArray(first) 6 | ? [first, ...flatten(rest)] 7 | : [...flatten(first), ...flatten(rest)]; // <2> 8 | }; 9 | 10 | const flattened = flatten([ 11 | [1, 2], 12 | [3], 4, 5, [6, 7], 13 | ]); 14 | 15 | console.assert(flattened.length === 7); 16 | console.assert(flattened.join() === '1,2,3,4,5,6,7'); 17 | 18 | // end::destruct-rest-params[] 19 | export default flatten; 20 | -------------------------------------------------------------------------------- /src/chapter04/130-object-destructuring.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::object-destructuring[] 3 | 4 | const paip = { 5 | name: 'Paradigms of Artificial Intelligence Programming', 6 | author: 'Peter Norvig', 7 | isbn: 1558601910, 8 | }; // <1> 9 | 10 | const { 11 | name: n, 12 | isbn: id, 13 | } = paip; // <2> 14 | 15 | console.assert(n === 'Paradigms of Artificial Intelligence Programming'); 16 | console.assert(id === 1558601910); 17 | 18 | const { 19 | name, 20 | isbn, 21 | } = paip; // <3> 22 | 23 | console.assert(name === 'Paradigms of Artificial Intelligence Programming'); 24 | console.assert(isbn === 1558601910); 25 | // end::object-destructuring[] 26 | export { 27 | paip, 28 | n, 29 | id, 30 | name, 31 | isbn, 32 | }; 33 | -------------------------------------------------------------------------------- /src/chapter04/140-object-destructuring-all.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-shadow,arrow-body-style */ 2 | /* eslint-disable no-console */ 3 | 4 | // tag::object-destructuring-all[] 5 | const config = { 6 | size: 200, 7 | transitionMs: 750, 8 | clip: { 9 | width: 200, 10 | }, 11 | }; // <1> 12 | 13 | const { 14 | size, 15 | transitionMs, 16 | clip: { // <2> 17 | width: w = 100, // <3> 18 | height = 100, 19 | } = {}, // <4> 20 | } = config; 21 | 22 | console.assert(size === 200); 23 | console.assert(transitionMs === 750); 24 | console.assert(w === 200); 25 | console.assert(height === 100); 26 | 27 | const drawChart = ({ 28 | size = 200, 29 | transitionMs = 1000, 30 | clip: { 31 | width: w = 100, 32 | height = 100, 33 | } = {}, 34 | } = {}) => { // <5> 35 | return [size, transitionMs, w, height]; 36 | }; 37 | 38 | // invoke it 39 | drawChart(); 40 | // end::object-destructuring-all[] 41 | export { 42 | config, 43 | size, 44 | transitionMs, 45 | w, 46 | height, 47 | drawChart, 48 | }; 49 | -------------------------------------------------------------------------------- /src/chapter04/150-convoluted-lookup-with-destructuring.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable prefer-template */ 3 | 4 | // tag::combination-lookup[] 5 | const user = { 6 | name: 'douglas', 7 | profession: 'developer', 8 | address: { 9 | street1: '1 Ad Infinitum Drive', 10 | street2: '', 11 | city: 'Cupertino', 12 | state: 'CA', 13 | zip: [ 14 | '95014', 15 | '1234', 16 | ], 17 | }, 18 | }; 19 | 20 | const { // <1> 21 | address: { // <2> 22 | zip: [ // <3> 23 | zip, // <4> 24 | extended, 25 | ], 26 | }, 27 | } = user; 28 | 29 | const final = zip + '-' + extended; 30 | console.assert(final === '95014-1234'); 31 | 32 | // end::combination-lookup[] 33 | export default final; 34 | -------------------------------------------------------------------------------- /src/chapter04/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter05/005-interpolation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable prefer-template */ 3 | // tag::005-interpolation[] 4 | const salutation = 'Mr.'; 5 | const name = 'Edgar'; 6 | const middle = 'Allen'; 7 | const last = 'Poe'; 8 | 9 | const fullName = (salutation ? salutation + ' ' : '') // <1> 10 | + name + ' ' + middle.trim() + ' ' + last; // <2> 11 | // prints 'Mr. Edgar Allen Poe' 12 | console.log(fullName); 13 | // end::005-interpolation[] 14 | export default fullName; 15 | -------------------------------------------------------------------------------- /src/chapter05/010-simple-template-literal.js: -------------------------------------------------------------------------------- 1 | // tag::010-simple-template-literal[] 2 | const greeting = 'Hola'; // <1> 3 | const name = 'Daniel'; 4 | 5 | const msg = `${greeting}! My name is ${name}`; // <2> 6 | // end::010-simple-template-literal[] 7 | export default msg; 8 | -------------------------------------------------------------------------------- /src/chapter05/020-nested-interpolation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::020-nested-interpolation[] 3 | // for illustrative purposes _ marks a whitespace 4 | { 5 | const name = 'Edgar'; 6 | const middle = 'Allen'; 7 | const last = 'Poe'; 8 | 9 | // prints 'Edgar_Allen_Poe' 10 | console.log(`${name} ${middle} ${last}`); // <1> 11 | } 12 | 13 | { 14 | const name = 'Emily'; 15 | const middle = ''; 16 | const last = 'Dickinson'; 17 | 18 | // prints 'Emily__Dickinson' 19 | console.log(`${name} ${middle} ${last}`); 20 | // prints 'Emily__Dickinson' // <2> 21 | console.log(`${name} ${middle.trim()} ${last}`); 22 | // console.log(`${${name} ${middle}}.trim() ${last}`); // <3> 23 | // prints Emily_Dickinson 24 | console.log(`${`${name} ${middle}`.trim()} ${last}`); // <4> 25 | } 26 | 27 | // end::020-nested-interpolation[] 28 | // export default msg; 29 | -------------------------------------------------------------------------------- /src/chapter05/030-escaping-literals.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable quotes */ 3 | // tag::030-escaping-literals[] 4 | 5 | const escapingLiterals = `Template strings introduce \`\` and use $\{} for interpolation`; 6 | // prints 'Template strings introduce `` and use ${} for interpolation' 7 | console.log(escapingLiterals); 8 | 9 | // end::030-escaping-literals[] 10 | export default escapingLiterals; 11 | -------------------------------------------------------------------------------- /src/chapter05/040-static-vs-dynamic.js: -------------------------------------------------------------------------------- 1 | // tag::040-static-vs-dynamic[] 2 | 3 | const greeting = 'Hello'; 4 | const name = 'Sylvia'; 5 | const msg = `${greeting}! My name is ${name}!`; // <1> 6 | // ___________-------------_______^ // <2> 7 | 8 | const fixedStrings = ['', '! My name is ', '!']; // <3> 9 | const values = ['Hello', 'Sylvia']; // <4> 10 | 11 | // end::040-static-vs-dynamic[] 12 | export { 13 | msg, 14 | greeting, 15 | name, 16 | fixedStrings, 17 | values, 18 | }; 19 | -------------------------------------------------------------------------------- /src/chapter05/050-reimplement-template-strings.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::050-reimplement-template-strings[] 3 | const handler = (strings, ...values) => { // <1> 4 | const interleave = (arr1, arr2) => arr1.reduce((arr, v, i) => arr.concat(v, arr2[i]), []); 5 | 6 | return interleave(strings, values).join(''); 7 | }; 8 | 9 | const greeting = 'Hello'; 10 | const name = 'Ernest'; 11 | 12 | const msg = handler`${greeting}! My name is ${name}.`; // <2> 13 | // prints 'Hello! My name is Ernest.' 14 | console.log(msg); 15 | // end::050-reimplement-template-strings[] 16 | export { 17 | handler, 18 | greeting, 19 | name, 20 | msg, 21 | }; 22 | -------------------------------------------------------------------------------- /src/chapter05/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter06/010-objects-keys-strings.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable quote-props, no-dupe-keys, dot-notation */ 3 | // tag::objects-keys-strings[] 4 | const obj1 = { 5 | 'true': 'String', 6 | true: 'Boolean', 7 | }; // <1> 8 | 9 | console.assert(obj1[true] === 'Boolean'); // <2> 10 | 11 | const obj2 = { 12 | true: 'Boolean', 13 | 'true': 'String', 14 | }; // <3> 15 | 16 | console.assert(obj2[true] === 'String'); // <4> 17 | // end::objects-keys-strings[] 18 | export { 19 | obj1, 20 | obj2, 21 | }; 22 | -------------------------------------------------------------------------------- /src/chapter06/020-maps-construction-manipulation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::maps-construction-manipulation[] 3 | const obj = {}; 4 | const map = new Map(); // <1> 5 | 6 | map.set('string', 'is a string'); // <2> 7 | map.set(true, 'is a boolean'); 8 | 9 | map.set(1, 'is a number').set(obj, 'is an object'); // <3> 10 | 11 | console.assert(map.has(1)); // <4> 12 | console.assert(map.get(obj) === 'is an object'); // <5> 13 | 14 | map.set(1, 'overrides first'); // <6> 15 | console.assert(map.get(1) === 'overrides first'); // <7> 16 | 17 | console.assert(map.delete('string')); // <8> 18 | console.assert(map.has('string') === false); 19 | 20 | console.assert(map.delete({}) === false); // <9> 21 | 22 | // end::maps-construction-manipulation[] 23 | export { 24 | obj, 25 | map, 26 | }; 27 | -------------------------------------------------------------------------------- /src/chapter06/030-maps-whole-manipulation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::maps-whole-api[] 3 | const map = new Map([ // <1> 4 | ['s', 'is a string'], // <2> 5 | [true, 'is a boolean', 'willBeIgnored'], // <3> 6 | [1], // <4> 7 | [], // <5> 8 | ]); 9 | 10 | console.assert(map.size === 4); // <6> 11 | 12 | console.assert(map.get('s') === 'is a string'); 13 | console.assert(map.get(true) === 'is a boolean'); 14 | console.assert(map.get(1) === undefined); 15 | 16 | console.assert(map.get(undefined) === undefined); 17 | console.assert(map.has(undefined)); 18 | 19 | map.forEach((v, k) => console.log(v, k)); // <7> 20 | 21 | console.log(map.entries()); 22 | console.log(map.keys()); 23 | console.log(map.values()); // <8> 24 | map.clear(); // <9> 25 | console.assert(map.size === 0); 26 | // end::maps-whole-api[] 27 | 28 | export default map; 29 | -------------------------------------------------------------------------------- /src/chapter06/040-spreading-maps.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::spreading-maps[] 3 | const firstQuarter = new Map([ 4 | [1, 'Jan'], 5 | [2, 'Feb'], 6 | [3, 'Mar'], 7 | [4, 'Apr'], 8 | ]); // <1> 9 | 10 | const mapToStr = [...firstQuarter].join(':'); // <2> 11 | console.assert(mapToStr === '1,Jan:2,Feb:3,Mar:4,Apr'); 12 | 13 | const [, 14 | [n2, m2], 15 | [n3, m3], 16 | ] = firstQuarter; // <3> 17 | 18 | console.assert(n2 === 2); 19 | console.assert(m2 === 'Feb'); 20 | console.assert(n3 === 3); 21 | console.assert(m3 === 'Mar'); 22 | 23 | // end::spreading-maps[] 24 | export default firstQuarter; 25 | -------------------------------------------------------------------------------- /src/chapter06/050-maps-from-other-maps.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::concatenating-maps[] 3 | const nihar = new Map([ 4 | ['car', 'mazda'], 5 | ['residence', 'apartment'], 6 | ]); 7 | 8 | const ericka = new Map([ 9 | ['pet', 'oscar'], 10 | ['residence', 'house'], 11 | ]); 12 | 13 | const union = new Map([...nihar, ...ericka]); // <1> 14 | 15 | console.assert(union.get('car') === 'mazda'); 16 | console.assert(union.get('residence') === 'house'); // <2> 17 | console.assert(union.get('pet') === 'oscar'); 18 | // end::concatenating-maps[] 19 | 20 | export default union; 21 | -------------------------------------------------------------------------------- /src/chapter06/055-no-literals-for-maps.js: -------------------------------------------------------------------------------- 1 | // tag::055-no-literals-for-maps[] 2 | const kiran = { // <1> 3 | name: 'kiran', 4 | profession: 'pharmacist', 5 | }; 6 | 7 | const favFruits = [ // <2> 8 | 'mango', 9 | 'guava', 10 | 'pineapple', 11 | ]; 12 | 13 | const numbersInHindi = new Map(); // <3> 14 | numbersInHindi.set(1, 'ek').set(2, 'do').set(3, 'teen'); 15 | 16 | // end::055-no-literals-for-maps[] 17 | export { 18 | kiran, 19 | favFruits, 20 | numbersInHindi, 21 | }; 22 | -------------------------------------------------------------------------------- /src/chapter06/060-maps-to-from-json.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::serializing-maps[] 3 | const nihar = new Map([ 4 | ['car', 'mazda'], 5 | ['residence', 'apartment'], 6 | ]); 7 | 8 | const mapToJson = map => JSON.stringify([...map]); // <1> 9 | const jsonToMap = mapStr => new Map(JSON.parse(mapStr)); // <2> 10 | 11 | const serialized = mapToJson(nihar); 12 | // prints '[["car","mazda"],["residence","apartment"]]' 13 | console.log(serialized); 14 | 15 | const deserialized = jsonToMap(serialized); 16 | // prints 'Map { 'car' => 'mazda', 'residence' => 'apartment' }' 17 | console.log(deserialized); 18 | 19 | // end::serializing-maps[] 20 | export { 21 | nihar, 22 | serialized, 23 | deserialized, 24 | }; 25 | -------------------------------------------------------------------------------- /src/chapter06/070-maps-to-from-json-fail.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable max-len */ 3 | // tag::serializing-maps-fail[] 4 | const obj = { 5 | name: 'some object', 6 | }; 7 | 8 | const map = new Map([ 9 | [obj, 'value against an object key'], 10 | ]); 11 | 12 | const mapToJson = m => JSON.stringify([...m]); 13 | const jsonToMap = mapStr => new Map(JSON.parse(mapStr)); 14 | 15 | const serialized = mapToJson(map); // <1> 16 | // prints '[[{"name":"some object"},"value against an object key"]]' 17 | console.log(serialized); 18 | 19 | const deserialized = jsonToMap(serialized); // <2> 20 | // prints 'Map { { name: 'some object' } => 'value against an object key' }' 21 | console.log(deserialized); 22 | console.assert(deserialized.get(obj) === undefined); // <3> 23 | // end::serializing-maps-fail[] 24 | export { 25 | map, 26 | serialized, 27 | deserialized, 28 | }; 29 | -------------------------------------------------------------------------------- /src/chapter06/080-maps-hard-references.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable import/no-mutable-exports */ 3 | // tag::maps-hard-references[] 4 | let obj = { 5 | name: 'some object', 6 | }; // <1> 7 | 8 | const map = new Map([ 9 | [obj, 'value against an object key'], // <2> 10 | ]); 11 | 12 | console.assert(map.has(obj)); 13 | 14 | obj = null; // <3> 15 | 16 | console.assert(map.size === 1); // <4> 17 | // end::maps-hard-references[] 18 | export { 19 | obj, 20 | map, 21 | }; 22 | -------------------------------------------------------------------------------- /src/chapter06/090-sets-construction-manipulation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::sets-construction-manipulation[] 3 | const obj = {}; 4 | const set = new Set(); // <1> 5 | 6 | set.add('string'); // <2> 7 | set.add(true); 8 | 9 | set.add(1).add(obj); // <3> 10 | 11 | console.assert(set.size === 4); 12 | 13 | console.assert(set.has(1)); // <4> 14 | 15 | set.add(1); // <5> 16 | console.assert(set.size === 4); // <6> 17 | 18 | console.assert(set.delete('string')); // <7> 19 | console.assert(set.has('string') === false); 20 | 21 | console.assert(set.delete({}) === false); // <8> 22 | // end::sets-construction-manipulation[] 23 | export { 24 | obj, 25 | set, 26 | }; 27 | -------------------------------------------------------------------------------- /src/chapter06/100-sets-whole-manipulation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::sets-whole-api[] 3 | const set = new Set([ // <1> 4 | 'string', 5 | true, 6 | 1, // <2> 7 | ]); 8 | 9 | console.assert(set.size === 3); // <3> 10 | 11 | console.assert(set.has('string')); 12 | console.assert(set.has(true)); 13 | console.assert(set.has(1)); 14 | 15 | set.forEach(k => console.log(k)); // <4> 16 | 17 | console.log(set.entries()); 18 | console.log(set.keys()); // <5> 19 | console.log(set.values()); // <6> 20 | 21 | set.clear(); // <7> 22 | console.assert(set.size === 0); 23 | 24 | // end::sets-whole-api[] 25 | 26 | export default set; 27 | -------------------------------------------------------------------------------- /src/chapter06/110-sets-from-other-set.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::concatenating-sets[] 3 | const colorsOne = new Set([ 4 | 'red', 5 | 'blue', 6 | ]); 7 | 8 | const colorsTwo = new Set([ 9 | 'yellow', 10 | 'blue', 11 | ]); 12 | 13 | const union = new Set([...colorsOne, ...colorsTwo]); // <1> 14 | 15 | console.assert(union.has('red')); 16 | console.assert(union.has('blue')); // <2> 17 | console.assert(union.has('yellow')); 18 | // end::concatenating-sets[] 19 | 20 | export default union; 21 | -------------------------------------------------------------------------------- /src/chapter06/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter07/010-object-literal-getters-setters.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, no-underscore-dangle */ 2 | /* eslint-disable object-shorthand, func-names */ 3 | // tag::object-literal-getter-setter[] 4 | const song = { 5 | name: 'Yellow Submarine', // <1> 6 | get duration() { // <2> 7 | console.log('Getter is invoked'); 8 | return this._duration ? (this._duration / 60) : 0; 9 | }, 10 | set duration(inMin) { // <3> 11 | if (inMin <= 0) { // <4> 12 | throw new Error('duration of song cannot be less or equal to 0 min'); 13 | } 14 | console.log(`Setter is invoked with ${inMin}`); 15 | this._duration = inMin * 60; // <5> 16 | }, 17 | getName: function () { // <6> 18 | return this.name; 19 | }, 20 | }; 21 | 22 | console.assert(song.name === 'Yellow Submarine'); // <7> 23 | 24 | // song.duration = -1; // <8> 25 | song.duration = 3.00; // <9> 26 | console.assert(song.duration === 3); // <10> 27 | 28 | console.assert(song.getName() === 'Yellow Submarine'); // <11> 29 | // end::object-literal-getter-setter[] 30 | 31 | export default song; 32 | -------------------------------------------------------------------------------- /src/chapter07/020-object-literal-computed-property.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable dot-notation, func-names */ 3 | // tag::object-literal-computed-property[] 4 | const getterFor = (prop) => { // <1> 5 | const capitalized = prop.charAt(0).toUpperCase() + prop.slice(1); // <2> 6 | return `get${capitalized}`; 7 | }; 8 | 9 | const song = { 10 | name: 'All You Need Is Love', 11 | album: 'Yellow Submarine', 12 | }; 13 | 14 | song[getterFor('name')] = function () { // <3> 15 | return song['name']; 16 | }; 17 | 18 | song[getterFor('album')] = function () { 19 | return song['album']; 20 | }; 21 | 22 | console.assert(song.getName() === song.name); 23 | console.assert(song.getAlbum() === song.album); 24 | // end::object-literal-computed-property[] 25 | 26 | export default song; 27 | -------------------------------------------------------------------------------- /src/chapter07/025-revealing-module-pattern.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable object-shorthand, func-names */ 3 | // tag::revealing-module-pattern[] 4 | 5 | const greeter = (function () { 6 | let greeting = 'Hello'; // <1> 7 | 8 | const exclaim = msg => `${msg}!`; // <2> 9 | 10 | const greet = name => exclaim(`${greeting} ${name}`); 11 | 12 | const salutation = (newGreeting) => { 13 | greeting = newGreeting; 14 | }; 15 | 16 | return { 17 | greet: greet, 18 | salutation: salutation, 19 | }; // <3> 20 | }()); // <4> 21 | 22 | console.assert(greeter.greet('Mason') === 'Hello Mason!'); 23 | greeter.salutation('Hola'); 24 | console.assert(greeter.greet('Micah') === 'Hola Micah!'); 25 | 26 | // end::revealing-module-pattern[] 27 | export default greeter; 28 | -------------------------------------------------------------------------------- /src/chapter07/050-object-literal-method-shorthand.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-underscore-dangle */ 3 | // tag::object-literal-method-shorthand[] 4 | const song = { 5 | name: 'Yellow Submarine', // <1> 6 | get duration() { // <2> 7 | console.log('Getter is invoked'); 8 | return this._duration ? (this._duration / 60) : 0; 9 | }, 10 | set duration(inMin) { // <3> 11 | if (inMin <= 0) { // <4> 12 | throw new Error('duration of song cannot be less or equal to 0 min'); 13 | } 14 | console.log(`Setter is invoked with ${inMin}`); 15 | this._duration = inMin * 60; // <5> 16 | }, 17 | getName() { // <1> 18 | return this.name; 19 | }, 20 | setName(name) { // <2> 21 | this.name = name; 22 | }, 23 | }; 24 | 25 | console.assert(song.getName() === 'Yellow Submarine'); 26 | song.setName('All You Need Is Love'); 27 | console.assert(song.getName() === 'All You Need Is Love'); 28 | // end::object-literal-method-shorthand[] 29 | 30 | export default song; 31 | -------------------------------------------------------------------------------- /src/chapter07/060-object-literal-inline-computed-property.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // tag::object-literal-inline-computed-property[] 4 | const getterFor = (prop) => { // <1> 5 | const capitalized = prop.charAt(0).toUpperCase() + prop.slice(1); // <2> 6 | return `get${capitalized}`; 7 | }; 8 | 9 | const song = { 10 | name: 'All You Need Is Love', 11 | album: 'Yellow Submarine', 12 | [getterFor('name')]() { // <3> 13 | return song.name; 14 | }, 15 | [getterFor('album')]() { 16 | return song.album; 17 | }, 18 | }; 19 | 20 | console.assert(song.getName() === song.name); 21 | console.assert(song.getAlbum() === song.album); 22 | // end::object-literal-inline-computed-property[] 23 | 24 | export default song; 25 | -------------------------------------------------------------------------------- /src/chapter07/070-revealing-module-pattern-shorthand.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable func-names */ 3 | 4 | // tag::revealing-module-pattern-shorthand[] 5 | 6 | const greeter = (function () { 7 | let greeting = 'Hello'; 8 | 9 | const exclaim = msg => `${msg}!`; // <2> 10 | 11 | const greet = name => exclaim(`${greeting} ${name}`); 12 | 13 | const salutation = (newGreeting) => { 14 | greeting = newGreeting; 15 | }; 16 | 17 | return { 18 | greet, // <1> 19 | salutation, 20 | }; 21 | // equivalent to 22 | /* 23 | return { 24 | greet: greet, 25 | salutation: salutation 26 | } 27 | */ 28 | }()); 29 | 30 | console.assert(greeter.greet('Mason') === 'Hello Mason!'); 31 | greeter.salutation('Hola'); 32 | console.assert(greeter.greet('Micah') === 'Hola Micah!'); 33 | 34 | // end::revealing-module-pattern-shorthand[] 35 | 36 | export default greeter; 37 | -------------------------------------------------------------------------------- /src/chapter07/080-trailing-comma-arrays-objects.js: -------------------------------------------------------------------------------- 1 | // tag::080-trailing-comma-arrays-objects[] 2 | const friedmanBooks = [ 3 | 'The Little Schemer', 4 | 'The Seasoned Schemer', 5 | 'The Reasoned Schemer', // <1> 6 | ]; 7 | 8 | const hoyteBook = { 9 | name: 'Let Over Lambda', 10 | author: 'Doug Hoyte', 11 | isbn10: '1435712757', // <2> 12 | }; 13 | // end::080-trailing-comma-arrays-objects[] 14 | 15 | export { 16 | friedmanBooks, 17 | hoyteBook, 18 | }; 19 | -------------------------------------------------------------------------------- /src/chapter07/090-trailing-comma-functions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // tag::090-trailing-comma-functions[] 4 | const rate = ( 5 | book, 6 | starCount, // <1> 7 | ) => `You rated '${book}' ${starCount} stars`; 8 | 9 | const rating = rate( 10 | 'Practical Common Lisp', 11 | 5, // <2> 12 | ); 13 | // prints 'You rated 'Practical Common Lisp' 5 stars' 14 | console.log(rating); 15 | // end::090-trailing-comma-functions[] 16 | export default rate; 17 | -------------------------------------------------------------------------------- /src/chapter07/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter08/040-symbols-are-unique.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable symbol-description */ 3 | 4 | // tag::symbols-are-unique[] 5 | const symbol1 = Symbol(); 6 | const symbol2 = Symbol(); // <1> 7 | console.assert(symbol1 !== symbol2); // <2> 8 | 9 | const symbol3 = Symbol('unique'); // <3> 10 | // prints Symbol(unique) 11 | console.log(symbol3); // <4> 12 | 13 | // end::symbols-are-unique[] 14 | export { 15 | symbol1, 16 | symbol2, 17 | symbol3, 18 | }; 19 | -------------------------------------------------------------------------------- /src/chapter08/050-overriding-object-keys-with-symbols.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable quote-props, func-names */ 2 | 3 | // tag::overriding-object-keys-with-symbols[] 4 | const ITERATOR = Symbol('iterator'); // <1> 5 | 6 | const iterableObject = { 7 | name: 'iterable', 8 | }; // <2> 9 | 10 | iterableObject[ITERATOR] = function () { 11 | return 'I am iterable'; 12 | }; // <3> 13 | 14 | const objWithExistingKey = { 15 | iterator: 'some value', 16 | }; // <4> 17 | 18 | objWithExistingKey[ITERATOR] = () => 'Works!'; // <5> 19 | // end::overriding-object-keys-with-symbols[] 20 | export { 21 | ITERATOR, 22 | iterableObject, 23 | objWithExistingKey, 24 | }; 25 | -------------------------------------------------------------------------------- /src/chapter08/070-method-hook-using-symbols.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::method-hook-using-symbols[] 3 | const LOG_LEVEL = Symbol('log'); // <1> 4 | const DEBUG = 'DEBUG'; 5 | const INFO = 'INFO'; 6 | const ERROR = 'ERROR'; 7 | 8 | const simpleLogger = (obj, msg) => { 9 | let returnMsg; 10 | switch (obj[LOG_LEVEL]) { // <2> 11 | case DEBUG: 12 | returnMsg = `DEBUG: ${msg}`; 13 | break; 14 | case INFO: 15 | returnMsg = `INFO: ${msg}`; 16 | break; 17 | case ERROR: 18 | returnMsg = `ERROR: ${msg}`; 19 | break; 20 | default: 21 | throw new Error('Invalid LOG_LEVEL'); 22 | } 23 | console.log(returnMsg); 24 | return returnMsg; 25 | }; 26 | 27 | const loggableObj = { 28 | log: 'this is just an ordinary property', 29 | [LOG_LEVEL]: INFO, // <3> 30 | }; 31 | 32 | simpleLogger(loggableObj, 'this is a test'); // <4> 33 | 34 | // end::method-hook-using-symbols[] 35 | export { 36 | LOG_LEVEL, 37 | DEBUG, 38 | INFO, 39 | ERROR, 40 | simpleLogger, 41 | loggableObj, 42 | }; 43 | -------------------------------------------------------------------------------- /src/chapter08/100-symbol-for.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::symbol-for[] 3 | 4 | const global = Symbol.for('globally visible'); // <1> 5 | const otherGlobal = Symbol.for('globally visible'); // <2> 6 | 7 | // prints 'true' 8 | console.log(global === otherGlobal); // <3> 9 | // end::symbol-for[] 10 | 11 | export { 12 | global, 13 | otherGlobal, 14 | }; 15 | -------------------------------------------------------------------------------- /src/chapter08/110-symbol-keyFor.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::symbol-keyFor[] 3 | 4 | const global = Symbol.for('a unique key'); // <1> 5 | const key = Symbol.keyFor(global); // <2> 6 | 7 | // prints 'true' 8 | console.log(key === 'a unique key'); 9 | // end::symbol-keyFor[] 10 | export { 11 | global, 12 | key, 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /src/chapter08/120-string-match.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::string-match[] 3 | 4 | const url = 'https://admin:supersecret@gitlab.com/looselytyped/sample-repo.git'; // <1> 5 | const split = url.match(/\w+:\w+/); // <2> 6 | 7 | // prints 8 | // [ 9 | // 'admin:supersecret', 10 | // index: 8, 11 | // input: 'https://admin:supersecret@gitlab.com/looselytyped/sample-repo.git', 12 | // groups: undefined 13 | // ] 14 | console.log(split); 15 | 16 | // end::string-match[] 17 | export { 18 | url, 19 | split, 20 | }; 21 | -------------------------------------------------------------------------------- /src/chapter08/130-symbol-match.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::symbol-splitter[] 3 | const passwordObfuscator = { // <1> 4 | regex: /\w+:\w+/, 5 | [Symbol.match](str) { // <2> 6 | const creds = str.match(this.regex); 7 | if (creds) { 8 | const [username] = creds[0].split(':'); // <3> 9 | return [ 10 | `${username}:***********`, // <4> 11 | ]; 12 | } 13 | return creds; 14 | }, 15 | }; 16 | 17 | const url = 'https://admin:supersecret@gitlab.com/looselytyped/sample-repo.git'; 18 | const credentials = url.match(passwordObfuscator); // <5> 19 | // prints 'obfuscated credentials [ 'admin:***********' ]' 20 | console.log('obfuscated credentials', credentials); 21 | 22 | // end::symbol-splitter[] 23 | export { 24 | passwordObfuscator, 25 | credentials, 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /src/chapter08/140-object-enumerate-keys.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable symbol-description, import/prefer-default-export */ 3 | 4 | // tag::object-enumerate-keys[] 5 | const obj = { 6 | a: 'a simple property', // <1> 7 | [Symbol()]: 'a symbol property', // <2> 8 | }; 9 | 10 | Object.defineProperty(obj, 'nonenumerable', { // <3> 11 | value: 'an unenumerable property', 12 | enumerable: false, 13 | }); 14 | 15 | // prints only '[ 'a' ]' 16 | console.log(Object.keys(obj)); 17 | // prints '[ 'a', 'nonenumerable' ]' 18 | console.log(Object.getOwnPropertyNames(obj)); 19 | // prints only '{"a":"a simple property"}' 20 | console.log(JSON.stringify(obj)); // <4> 21 | // end::object-enumerate-keys[] 22 | 23 | export { 24 | obj, 25 | }; 26 | -------------------------------------------------------------------------------- /src/chapter08/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter09/010-for-in-loop-arrays.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable guard-for-in, no-restricted-syntax, import/prefer-default-export */ 3 | 4 | // tag::010-for-in-loop-arrays[] 5 | const arr = ['a']; // <1> 6 | 7 | for (const k in arr) { 8 | console.assert(k === '0'); // <2> 9 | console.log(arr[k]); // <3> 10 | } 11 | 12 | // end::010-for-in-loop-arrays[] 13 | export { 14 | arr, 15 | }; 16 | -------------------------------------------------------------------------------- /src/chapter09/035-for-of-loop-array.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-plusplus, no-restricted-syntax, import/prefer-default-export */ 3 | // tag::035-for-of-loop-array[] 4 | const arr = ['a', 'b', 'c']; // <1> 5 | 6 | for (const k of arr) { // <2> 7 | // prints `a`, 'b', 'c' in sequence 8 | console.log(k); // <3> 9 | } 10 | // end::035-for-of-loop-array[] 11 | export default arr; 12 | -------------------------------------------------------------------------------- /src/chapter09/040-loops-for-of-all-datastructures.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-restricted-syntax */ 3 | // tag::040-loops-for-of-all-datastructures[] 4 | 5 | const array = [10, 20, 30, 40, 50]; 6 | for (const i of array) { 7 | console.log(i); 8 | } 9 | 10 | const set = new Set(['a', 'set', true, false]); 11 | for (const i of set) { 12 | console.log(i); 13 | } 14 | 15 | const map = new Map([ 16 | ['s', 'is a string'], 17 | [true, 'is a boolean'], 18 | ]); 19 | for (const [k, v] of map) { // <1> 20 | console.log(`${k}->${v}`); 21 | } 22 | 23 | const string = 'ES6 is awesome!'; 24 | for (const i of string) { 25 | console.log(i); 26 | } 27 | // end::040-loops-for-of-all-datastructures[] 28 | export { 29 | array, 30 | set, 31 | map, 32 | string, 33 | }; 34 | -------------------------------------------------------------------------------- /src/chapter09/045-iterator-return.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-restricted-syntax, import/prefer-default-export */ 3 | /* eslint-disable func-names, object-shorthand, no-plusplus */ 4 | // tag::045-iterator-return[] 5 | 6 | const incrementor = { 7 | [Symbol.iterator]() { 8 | let start = 0; 9 | return { 10 | next() { 11 | return { 12 | value: start++, 13 | done: false, 14 | }; 15 | }, 16 | return: function () { // <1> 17 | console.log('Cleaning up ...'); 18 | return { 19 | done: true, 20 | }; 21 | }, 22 | }; 23 | }, 24 | }; 25 | 26 | for (const v of incrementor) { 27 | if (v > 10) { 28 | break; // <2> 29 | } 30 | console.log(v); 31 | } 32 | 33 | // end::045-iterator-return[] 34 | export { 35 | incrementor, 36 | }; 37 | -------------------------------------------------------------------------------- /src/chapter09/050-simple-generator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-restricted-syntax, import/prefer-default-export */ 3 | // tag::050-simple-generator[] 4 | 5 | function* generatorDemo() { 6 | yield 10; 7 | console.log('First time'); 8 | yield 20; 9 | console.log('Second time'); 10 | } 11 | 12 | const generator = generatorDemo(); // prints nothing to the log 13 | console.assert(generator !== undefined); 14 | 15 | // following each line is what you see in the console 16 | console.log(generator.next()); 17 | // { value: 10, done: false } 18 | console.log(generator.next()); 19 | // First time 20 | // { value: 20, done: false } 21 | console.log(generator.next()); 22 | // Second time 23 | // { value: undefined, done: true } 24 | 25 | // alternatively, we can just use the for-of loop 26 | for (const i of generatorDemo()) { 27 | console.log(i); 28 | } 29 | 30 | // end::050-simple-generator[] 31 | export { 32 | generatorDemo, 33 | }; 34 | -------------------------------------------------------------------------------- /src/chapter09/060-generator-fibonacci.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable import/prefer-default-export */ 3 | 4 | // tag::060-generator-fibonacci[] 5 | function* fibonacci() { 6 | let start = 0; 7 | let next = 1; 8 | yield start; 9 | yield next; 10 | while (true) { 11 | const result = start + next; 12 | start = next; 13 | next = result; 14 | yield result; 15 | } 16 | } 17 | 18 | const f = fibonacci(); 19 | console.log(f.next().value); // 0 20 | console.log(f.next().value); // 1 21 | console.log(f.next().value); // 1 22 | console.log(f.next().value); // 2 23 | console.log(f.next().value); // 3 24 | console.log(f.next().value); // 5 25 | console.log(f.next().value); // 8 26 | // end::060-generator-fibonacci[] 27 | export { 28 | fibonacci, 29 | }; 30 | -------------------------------------------------------------------------------- /src/chapter09/070-simple-generator-push.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable import/prefer-default-export */ 3 | 4 | // tag::070-simple-generator-push[] 5 | 6 | function* generatorWithPushDemo() { 7 | const first = yield 10; 8 | console.log('First time', first); 9 | const second = yield 20; 10 | console.log('Second time', second); 11 | } 12 | 13 | const generator = generatorWithPushDemo(); // prints nothing to the log 14 | console.assert(generator !== undefined); 15 | 16 | // following each line is what you see in the console 17 | console.log(generator.next()); // <1> 18 | // { value: 10, done: false } 19 | console.log(generator.next('sending a value in')); // <2> 20 | // First time sending a value in 21 | // { value: 20, done: false } 22 | console.log(generator.next('sending another value in')); // <3> 23 | // Second time sending another value in 24 | // { value: undefined, done: true } 25 | 26 | // end::070-simple-generator-push[] 27 | export { 28 | generatorWithPushDemo, 29 | }; 30 | -------------------------------------------------------------------------------- /src/chapter09/090-yield-generator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-restricted-syntax */ 3 | // tag::090-yield*-generator[] 4 | 5 | function* inner() { // <1> 6 | yield 'b'; 7 | yield 'c'; 8 | yield 'd'; 9 | } 10 | 11 | function* outer() { // <2> 12 | yield 'a'; 13 | console.log('after the first outer yield'); 14 | yield* [1, 2, 3]; // <3> 15 | console.log('after finishing the inner yield*'); 16 | yield 'e'; 17 | } 18 | 19 | for (const v of outer()) { 20 | console.log(v); 21 | } 22 | // a 23 | // after the first outer yield 24 | // b 25 | // c 26 | // d 27 | // after finishing the inner yield* 28 | // e 29 | 30 | // end::090-yield*-generator[] 31 | export { 32 | inner, 33 | outer, 34 | }; 35 | -------------------------------------------------------------------------------- /src/chapter09/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter10/010-basic-promise.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::010-basic-promise[] 3 | const shouldResolve = true; 4 | const p = new Promise((resolve, reject) => { // <1> 5 | if (shouldResolve) { 6 | resolve('I transitioned successfully'); // <2> 7 | } else { 8 | reject(new Error('I failed to resolve')); // <3> 9 | } 10 | }); 11 | // prints 'Promise { 'I transitioned successfully' }' 12 | console.log(p); 13 | // end::010-basic-promise[] 14 | 15 | export default p; 16 | -------------------------------------------------------------------------------- /src/chapter10/020-promisify-xhr.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | /* eslint-disable no-unused-vars, implicit-arrow-linebreak */ 3 | // DUPLICATED IN 030-promise-all.js! 4 | // tag::020-promisify-xhr[] 5 | const asyncRequest = (method, url) => // <1> 6 | new Promise((resolve, reject) => { 7 | const xhr = new XMLHttpRequest(); 8 | xhr.open(method, url, true); 9 | xhr.onload = () => resolve(xhr.response); // <2> 10 | xhr.onerror = () => reject(new Error(xhr.statusText)); // <3> 11 | xhr.send(); 12 | }); 13 | 14 | const req1 = asyncRequest('GET', 'https://my-json-server.typicode.com/typicode/demo/posts'); 15 | // end::020-promisify-xhr[] 16 | export default asyncRequest; 17 | -------------------------------------------------------------------------------- /src/chapter10/025-promisify-xhr-with-then-catch.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import asyncRequest from './020-promisify-xhr'; 3 | 4 | // tag::025-promisify-xhr-with-then-catch[] 5 | const req1 = asyncRequest('GET', 'https://my-json-server.typicode.com/typicode/demo/posts'); 6 | 7 | req1 8 | .then(json => JSON.parse(json)) // <1> 9 | .then(resp => resp.map(item => item.id)) 10 | .then((ids) => { 11 | console.log(`Found ${ids.length} posts`); 12 | return ids; 13 | }) 14 | .catch(err => console.log(err)); // <2> 15 | // end::025-promisify-xhr-with-then-catch[] 16 | export default asyncRequest; 17 | -------------------------------------------------------------------------------- /src/chapter10/030-promise-all.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-undef */ 3 | import asyncRequest from './020-promisify-xhr'; 4 | 5 | // tag::030-promise-all[] 6 | const p = asyncRequest('GET', 'https://my-json-server.typicode.com/typicode/demo/posts'); // <1> 7 | const c = asyncRequest('GET', 'https://my-json-server.typicode.com/typicode/demo/comments'); // <2> 8 | 9 | Promise.all([p, c]) // <3> 10 | .then(([posts, comments]) => ({ // <4> 11 | posts: JSON.parse(posts), 12 | comments: JSON.parse(comments), 13 | })) 14 | .then(obj => console.log(obj)) 15 | .catch(err => console.log(err)); 16 | // end::030-promise-all[] 17 | 18 | export default asyncRequest; 19 | -------------------------------------------------------------------------------- /src/chapter10/040-promise-race.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-undef */ 3 | // DUPLICATED IN 020-promisify-xhr.js!! 4 | import asyncRequest from './020-promisify-xhr'; 5 | 6 | // tag::040-promise-race[] 7 | const p = asyncRequest('GET', 'https://my-json-server.typicode.com/typicode/demo/posts'); // <1> 8 | const timer = new Promise((_, reject) => setTimeout(reject, 1000)); // <2> 9 | 10 | Promise.race([p, timer]) // <3> 11 | .then(posts => ({ // <4> 12 | posts: JSON.parse(posts), 13 | })) 14 | .catch(() => ({ // <5> 15 | posts: [], 16 | })) 17 | .then(obj => console.log(obj)); 18 | // end::040-promise-race[] 19 | 20 | export default asyncRequest; 21 | -------------------------------------------------------------------------------- /src/chapter10/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter11/010-basic-class.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable func-names */ 3 | // tag::010-basic-class[] 4 | function Person(name) { // <1> 5 | this.name = name; 6 | } 7 | 8 | Person.prototype.getName = function () { // <2> 9 | return this.name; 10 | }; 11 | 12 | Person.prototype.sayHello = function (to) { // <3> 13 | return `Hello ${to.getName()}. My name is ${this.name}.`; 14 | }; 15 | 16 | const raju = new Person('Raju'); 17 | const venkat = new Person('Venkat'); 18 | // prints 'Hello Venkat. My name is Raju' 19 | console.log(raju.sayHello(venkat)); 20 | // end::010-basic-class[] 21 | export { 22 | Person, 23 | raju, 24 | venkat, 25 | }; 26 | -------------------------------------------------------------------------------- /src/chapter11/015-basic-prototypal-inheritance.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable func-names */ 3 | import { 4 | Person, 5 | venkat, 6 | } from './010-basic-class'; 7 | 8 | // tag::015-basic-prototypal-inheritance[] 9 | function SuperHero(name, superpower) { // <1> 10 | // super call - can pass args 11 | Person.call(this, name); // <2> 12 | this.superpower = superpower; 13 | } 14 | 15 | SuperHero.prototype = Object.create(Person.prototype); // <3> 16 | 17 | SuperHero.prototype.warCry = function () { // <4> 18 | return `My name is ${this.name}!!!`; 19 | }; 20 | 21 | SuperHero.prototype.constructor = SuperHero; // <5> 22 | 23 | const thor = new SuperHero('Thor', 'Mjolnir'); 24 | // prints 'My name is Thor!!!' 25 | console.log(thor.warCry()); 26 | // prints 'Hello Venkat. My name is Thor' 27 | console.log(thor.sayHello(venkat)); 28 | // end::015-basic-prototypal-inheritance[] 29 | export { 30 | SuperHero, 31 | thor, 32 | }; 33 | -------------------------------------------------------------------------------- /src/chapter11/020-classes.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::020-classes[] 3 | class Person { // <1> 4 | constructor(name) { // <2> 5 | this.name = name; 6 | } 7 | 8 | getName() { // <3> 9 | return this.name; 10 | } 11 | 12 | sayHello(to) { // <4> 13 | return `Hello ${to.getName()}. My name is ${this.name}.`; 14 | } 15 | } 16 | 17 | const raju = new Person('Raju'); 18 | const venkat = new Person('Venkat'); 19 | // prints 'Hello Venkat. My name is Raju' 20 | console.log(raju.sayHello(venkat)); 21 | 22 | // end::020-classes[] 23 | export { 24 | Person, 25 | raju, 26 | venkat, 27 | }; 28 | -------------------------------------------------------------------------------- /src/chapter11/030-classes-prototypal-inheritance.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { 3 | Person, 4 | venkat, 5 | } from './020-classes'; 6 | 7 | // tag::030-classes-prototypal-inheritance[] 8 | class SuperHero extends Person { // <1> 9 | constructor(name, superpower) { // <2> 10 | super(name); // <3> 11 | this.superpower = superpower; 12 | } 13 | 14 | warCry() { // <4> 15 | return `My name is ${this.name}!!!`; 16 | } 17 | } 18 | 19 | const thor = new SuperHero('Thor', 'Mjolnir'); 20 | // prints 'My name is Thor!!!' 21 | console.log(thor.warCry()); 22 | // prints 'Hello Venkat. My name is Thor' 23 | console.log(thor.sayHello(venkat)); 24 | // end::030-classes-prototypal-inheritance[] 25 | export { 26 | SuperHero, 27 | thor, 28 | }; 29 | -------------------------------------------------------------------------------- /src/chapter11/040-classes-static-methods.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars, no-console */ 2 | import { 3 | Person, 4 | } from './020-classes'; 5 | 6 | // tag::040-classes-static-methods[] 7 | class SuperHero extends Person { 8 | constructor(name, superpower) { 9 | super(name); 10 | this.superpower = superpower; 11 | SuperHero.internalCount += 1; // <1> 12 | } 13 | 14 | static count() { // <2> 15 | return SuperHero.internalCount; 16 | } 17 | } 18 | SuperHero.internalCount = 0; // <3> 19 | 20 | const thor = new SuperHero('Thor', 'Mjolnir'); 21 | const blackWidow = new SuperHero('Black Widow', 'weapons specialist'); 22 | // prints 'We have 2 superheroes!' 23 | console.log(`We have ${SuperHero.count()} superheroes!`); // <4> 24 | // end::040-classes-static-methods[] 25 | export default SuperHero; 26 | -------------------------------------------------------------------------------- /src/chapter11/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter12/010-iefe-for-var.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-mutable-exports, no-plusplus, object-shorthand */ 2 | /* eslint-disable no-var, no-console */ 3 | // tag::iefe[] 4 | const counter = (function createCounter() { // <1> 5 | var steps = 0; // <2> 6 | function increment() { 7 | steps++; 8 | } 9 | function getCount() { 10 | return steps; 11 | } 12 | 13 | return { 14 | increment: increment, 15 | getCount: getCount, 16 | }; // <3> 17 | }()); 18 | // use it 19 | // console.log(steps); // <4> 20 | counter.increment(); // <5> 21 | console.assert(counter.getCount() === 1); // <6> 22 | // end::iefe[] 23 | export default counter; 24 | -------------------------------------------------------------------------------- /src/chapter12/020-named-inline-exports.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-properties */ 2 | // tag::020-named-inline-exports[] 3 | export const degreesToRadians = d => d * (Math.PI / 180); // <1> 4 | export const gradiansToRadians = g => g * 15.707 * Math.pow(10, -3); 5 | 6 | const calc = (fn, x, unit) => { // <2> 7 | switch (unit) { 8 | case 'degrees': 9 | return fn.call(null, degreesToRadians(x)); 10 | case 'gradians': 11 | return fn.call(null, gradiansToRadians(x)); 12 | default: 13 | return fn.call(null, x); 14 | } 15 | }; 16 | 17 | export const sin = (x, unit = 'degrees') => calc(Math.sin, x, unit); 18 | export const cos = (x, unit = 'degrees') => calc(Math.cos, x, unit); 19 | export const tan = (x, unit = 'degrees') => calc(Math.tan, x, unit); 20 | 21 | export const trig = { // <3> 22 | degreesToRadians, 23 | gradiansToRadians, 24 | sin, 25 | cos, 26 | tan, 27 | }; 28 | // end::020-named-inline-exports[] 29 | -------------------------------------------------------------------------------- /src/chapter12/060-named-imports.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::060-named-imports[] 3 | /* 4 | '030-named-exports' exports the following 5 | export { 6 | degreesToRadians, 7 | gradiansToRadians, 8 | sin, 9 | cos, 10 | tan, 11 | trig, 12 | } 13 | */ 14 | import { // <1> 15 | sin, 16 | cos, 17 | tan, 18 | } from './030-named-exports'; 19 | 20 | // use the functions 21 | console.log(sin(0)); 22 | // end::060-named-imports[] 23 | export { 24 | sin, 25 | cos, 26 | tan, 27 | }; 28 | -------------------------------------------------------------------------------- /src/chapter12/070-named-aliased-import.js: -------------------------------------------------------------------------------- 1 | // tag::070-named-aliased-import[] 2 | 3 | /* 4 | '050-alias-exports' exports the following 5 | export { 6 | degreesToRadians, 7 | gradiansToRadians, 8 | sin as sine, 9 | cos as cosine, 10 | tan, 11 | trig as trignometry, 12 | }; 13 | */ 14 | 15 | import { 16 | sine, // <1> 17 | cosine, 18 | tan, 19 | trignometry, 20 | } from './050-alias-exports'; 21 | // end::070-named-aliased-import[] 22 | 23 | // for testing 24 | export { 25 | sine, 26 | cosine, 27 | tan, 28 | trignometry, 29 | }; 30 | -------------------------------------------------------------------------------- /src/chapter12/080-wildcard-import.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::080-wildcard-import[] 3 | 4 | /* 5 | '050-alias-exports' exports the following 6 | export { 7 | degreesToRadians, 8 | gradiansToRadians, 9 | sin as sine, 10 | cos as cosine, 11 | tan, 12 | trig as trignometry, 13 | }; 14 | */ 15 | import * as trigFns from './050-alias-exports'; // <1> 16 | 17 | console.log(trigFns.sine(0)); // <2> 18 | // end::080-wildcard-import[] 19 | 20 | // for testing 21 | export default trigFns; 22 | -------------------------------------------------------------------------------- /src/chapter12/090-aliasing-imports.js: -------------------------------------------------------------------------------- 1 | // tag::090-aliasing-imports[] 2 | 3 | /* 4 | '030-named-exports' exports the following 5 | export { 6 | degreesToRadians, 7 | gradiansToRadians, 8 | sin, 9 | cos, 10 | tan, 11 | trig, 12 | } 13 | */ 14 | 15 | import { 16 | sin as sine, // <1> 17 | cos as cosine, 18 | trig as trignometry, 19 | } from './030-named-exports'; 20 | // end::090-aliasing-imports[] 21 | 22 | // for testing 23 | export { 24 | sine, 25 | cosine, 26 | trignometry, 27 | }; 28 | -------------------------------------------------------------------------------- /src/chapter12/100-default-import.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable import/no-named-as-default-member */ 3 | // tag::100-default-import[] 4 | 5 | /* 6 | '040-default-exports' exports the following 7 | export { 8 | degreesToRadians, 9 | gradiansToRadians, 10 | sin, 11 | cos, 12 | tan, 13 | }; 14 | 15 | export default trig; 16 | */ 17 | import myTrignometry, { // <1> 18 | sin, 19 | cos, 20 | tan, 21 | } from './040-default-exports'; 22 | 23 | console.log(myTrignometry.sin()); // <2> 24 | // end::100-default-import[] 25 | // for testing 26 | export { 27 | myTrignometry, 28 | sin, 29 | cos, 30 | tan, 31 | }; 32 | -------------------------------------------------------------------------------- /src/chapter12/110-default-with-aliased-imports.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable import/no-named-as-default-member */ 3 | // tag::110-default-with-aliased-imports[] 4 | 5 | /* 6 | '040-default-exports' exports the following 7 | export { 8 | degreesToRadians, 9 | gradiansToRadians, 10 | sin, 11 | cos, 12 | tan, 13 | }; 14 | 15 | export default trig; 16 | */ 17 | import myTrignometry, { // <1> 18 | sin as sine, // <2> 19 | cos as cosine, 20 | tan, 21 | } from './040-default-exports'; 22 | 23 | console.log(myTrignometry.sin()); // <3> 24 | console.log(sine(45)); 25 | 26 | // end::110-default-with-aliased-imports[] 27 | // for testing 28 | export { 29 | myTrignometry, 30 | sine, 31 | cosine, 32 | tan, 33 | }; 34 | -------------------------------------------------------------------------------- /src/chapter12/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter12/exporter.mjs: -------------------------------------------------------------------------------- 1 | // file name must end in "mjs" — like exporter.mjs 2 | export const sayHello = name => `Hello ${name}!!` 3 | -------------------------------------------------------------------------------- /src/chapter12/importer.mjs: -------------------------------------------------------------------------------- 1 | import { sayHello } from './exporter.mjs'; // <1> 2 | 3 | // prints 'Hello ES6 Modules!!' 4 | console.log(sayHello("ES6 Modules")); 5 | -------------------------------------------------------------------------------- /src/chapter13/010-array-prototype-equals.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-extend-native, no-console */ 2 | // tag::010-array-prototype-equals[] 3 | Object.defineProperty(Array.prototype, 'equals', { // <1> 4 | value(other) { 5 | if (!other) return false; 6 | if (!Array.isArray(other)) return false; 7 | if (this.length !== other.length) return false; 8 | 9 | const [fMe, ...rMe] = this; 10 | const [fOther, ...rOther] = other; 11 | 12 | if (fMe === fOther) { 13 | return true; 14 | } 15 | if ((rMe.length === 0) && (rOther.length === 0)) { 16 | return true; 17 | } 18 | return rMe.equals(rOther); 19 | }, 20 | enumerable: false, 21 | configurable: true, 22 | }); 23 | 24 | const first = [1, 2, 3, [4, 5]]; 25 | const second = [1, 2, 3, [4, 5]]; 26 | const third = [1, 2, 3]; 27 | 28 | // prints 'true' 29 | console.log(first.equals(second)); // <2> 30 | // prints 'false' 31 | console.log(first.equals(third)); 32 | // end::010-array-prototype-equals[] 33 | export default first; 34 | -------------------------------------------------------------------------------- /src/chapter13/030-simple-proxy.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | // tag::030-simple-proxy[] 3 | const toBeIntercepted = { // <1> 4 | name: 'Jonathan', 5 | getName() { 6 | return this.name; 7 | }, 8 | setName(name) { 9 | this.name = name; 10 | }, 11 | }; 12 | 13 | const proxied = new Proxy(toBeIntercepted, // <2> 14 | { // <3> 15 | get(target, property) { // <4> 16 | console.log(`${property} was called`); 17 | return target[property]; 18 | }, 19 | }); 20 | 21 | // prints 'name was called', followed by 'Jonathan' 22 | console.log(proxied.name); // <5> 23 | // prints 'getName was called', followed by 'Jonathan' 24 | console.log(proxied.getName()); 25 | // end::030-simple-proxy[] 26 | export { 27 | toBeIntercepted, 28 | proxied, 29 | }; 30 | -------------------------------------------------------------------------------- /src/chapter13/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter14/010-simple-math-imperatively.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | // tag::010-simple-math-imperatively[] 3 | const firstSyncOp = () => 10; // <1> 4 | const secondSyncOp = arg => arg + 20; 5 | const thirdSyncOp = arg => arg + 30; 6 | 7 | const firstSyncOpResult = firstSyncOp(); // <2> 8 | const secondSyncOpResult = secondSyncOp(firstSyncOpResult); 9 | const result = thirdSyncOp(secondSyncOpResult); 10 | 11 | // prints 'Using synchronous operations 60' 12 | console.log('Using synchronous operations', result); 13 | // end::010-simple-math-imperatively[] 14 | export { 15 | firstSyncOp, 16 | secondSyncOp, 17 | thirdSyncOp, 18 | result, 19 | }; 20 | -------------------------------------------------------------------------------- /src/chapter14/020-simple-math-using-promises.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | // tag::020-simple-math-using-promises[] 3 | const firstAsyncOp = () => new Promise(res => setTimeout(res, 10, 10)); // <1> 4 | const secondAsyncOp = arg => new Promise(res => setTimeout(res, 10, arg + 20)); 5 | const thirdAsyncOp = arg => Promise.resolve(arg + 30); 6 | 7 | const result = firstAsyncOp() 8 | .then(secondAsyncOp) // <2> 9 | .then(thirdAsyncOp); 10 | 11 | result.then((r) => { 12 | console.log('Using promises', r); 13 | return r; 14 | }); 15 | 16 | // end::020-simple-math-using-promises[] 17 | export { 18 | firstAsyncOp, 19 | secondAsyncOp, 20 | thirdAsyncOp, 21 | result, 22 | }; 23 | -------------------------------------------------------------------------------- /src/chapter14/030-simple-async.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable func-names, no-console, implicit-arrow-linebreak */ 2 | // tag::030-simple-async[] 3 | const implicitPromise = async () => 4 | ['Implicitly', 'wrapped', 'in', 'a', 'promise']; // <1> 5 | implicitPromise().then(console.log); 6 | 7 | const explicitPromise = async () => 8 | Promise.resolve(['This', 'just', 'returns', 'the', 'promise']); // <2> 9 | explicitPromise().then(console.log); 10 | // end::030-simple-async[] 11 | export { 12 | implicitPromise, 13 | explicitPromise, 14 | }; 15 | -------------------------------------------------------------------------------- /src/chapter14/040-simple-async-await.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | // tag::040-simple-async-await[] 3 | const firstAsyncOp = () => new Promise(res => setTimeout(res, 10, 10)); // <1> 4 | 5 | (async () => { // <2> 6 | const result = await firstAsyncOp(); // <3> 7 | // prints '10' 8 | console.log(result); 9 | return result; 10 | })(); 11 | // end::040-simple-async-await[] 12 | export default firstAsyncOp; 13 | -------------------------------------------------------------------------------- /src/chapter14/050-simple-math-using-async-await.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console, implicit-arrow-linebreak */ 2 | import { 3 | firstAsyncOp, 4 | secondAsyncOp, 5 | thirdAsyncOp, 6 | } from './020-simple-math-using-promises'; 7 | // tag::050-simple-math-using-async-await[] 8 | const result = (async () => { // <1> 9 | const firstAsyncOpResult = await firstAsyncOp(); // <2> 10 | const secondAsyncOpResult = await secondAsyncOp(firstAsyncOpResult); // <3> 11 | const res = await thirdAsyncOp(secondAsyncOpResult); 12 | 13 | return res; // <4> 14 | })(); 15 | 16 | result.then((r) => { // <5> 17 | console.log('Using async/await', r); 18 | return r; 19 | }); 20 | // end::050-simple-math-using-async-await[] 21 | export { 22 | firstAsyncOp, 23 | secondAsyncOp, 24 | thirdAsyncOp, 25 | result, 26 | }; 27 | -------------------------------------------------------------------------------- /src/chapter14/055-sync-async-conditional-again.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | import { 3 | firstAsyncOp, 4 | secondAsyncOp, 5 | thirdAsyncOp, 6 | } from './020-simple-math-using-promises'; 7 | 8 | // tag::055-sync-async-conditional-again[] 9 | const result = (async () => { 10 | let firstAsyncOpResult = await firstAsyncOp(); 11 | if (firstAsyncOpResult > 20) { // <1> 12 | firstAsyncOpResult = await secondAsyncOp(firstAsyncOpResult); 13 | } else { 14 | firstAsyncOpResult = await thirdAsyncOp(firstAsyncOpResult); 15 | } 16 | return firstAsyncOpResult; 17 | })(); 18 | 19 | result.then((r) => { 20 | // prints 'async/await conditional result: 40' 21 | console.log(`async/await conditional result: ${r}`); 22 | return r; 23 | }); 24 | // end::055-sync-async-conditional-again[] 25 | export default result; 26 | -------------------------------------------------------------------------------- /src/chapter14/060-fetch-with-async-await.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | import fetch from 'node-fetch'; 3 | // tag::060-fetch-with-async-await[] 4 | const getWithPromises = url => fetch(url).then(resp => resp.json()); // <1> 5 | const getWithAsyncAwait = async (url) => { // <2> 6 | const resp = await fetch(url); // <3> 7 | return resp.json(); // <4> 8 | }; 9 | 10 | const url = 'https://my-json-server.typicode.com/typicode/demo/comments'; 11 | 12 | getWithPromises(url) // <5> 13 | .then((json) => { 14 | console.log(json); 15 | return json; 16 | }); 17 | 18 | getWithAsyncAwait(url) // <6> 19 | .then((json) => { 20 | console.log(json); 21 | return json; 22 | }); 23 | 24 | // alternatively 25 | (async () => { 26 | // either one works just the same 27 | // const json = await getWithPromises(url); 28 | const json = await getWithAsyncAwait(url); // <7> 29 | console.log(json); 30 | })(); 31 | // end::060-fetch-with-async-await[] 32 | export { 33 | getWithPromises, 34 | getWithAsyncAwait, 35 | }; 36 | -------------------------------------------------------------------------------- /src/chapter14/065-error-trapping.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | // tag::065-error-trapping[] 3 | const firstAsyncOp = () => new Promise(res => setTimeout(res, 10, 10)); // <1> 4 | const secondAsyncOp = arg => new Promise(res => setTimeout(res, 10, arg + 20)); 5 | const thirdAsyncOp = () => Promise.reject(new Error('Oops!')); // <2> 6 | 7 | const result = (async () => { 8 | try { // <3> 9 | const firstAsyncOpResult = await firstAsyncOp(); 10 | const secondAsyncOpResult = await secondAsyncOp(firstAsyncOpResult); 11 | const res = await thirdAsyncOp(secondAsyncOpResult); 12 | 13 | return res; 14 | } catch (e) { 15 | console.error(e); // <4> 16 | return 0; 17 | } 18 | })(); 19 | 20 | result.then((r) => { 21 | // prints '0' 22 | console.log('Using async/await', r); 23 | return r; 24 | }); 25 | // end::065-error-trapping[] 26 | export { 27 | firstAsyncOp, 28 | secondAsyncOp, 29 | thirdAsyncOp, 30 | result, 31 | }; 32 | -------------------------------------------------------------------------------- /src/chapter14/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/chapter15/010-asynchronous-iteration.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | // tag::010-asynchronous-iteration[] 3 | const randomTimeout = async (val, index) => { 4 | const timeout = Math.floor(Math.random() * Math.floor(42)); // <1> 5 | return new Promise(res => setTimeout(res, timeout, `My value is ${val} at index: ${index}`)); // <2> 6 | }; 7 | 8 | const promiseList = [ 9 | randomTimeout(10, 1), 10 | randomTimeout(20, 2), 11 | randomTimeout(30, 3), 12 | ]; // <3> 13 | 14 | // prints the following (your ordering might vary) 15 | // My value is 20 at index: 2 16 | // My value is 10 at index: 1 17 | // My value is 30 at index: 3 18 | for (const p of promiseList) { 19 | p.then(console.log); // <4> 20 | } 21 | // end::010-asynchronous-iteration[] 22 | export default promiseList; 23 | export { 24 | randomTimeout, 25 | }; 26 | -------------------------------------------------------------------------------- /src/chapter15/020-asynchronous-generator-async-await.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | import { 3 | randomTimeout, 4 | } from './010-asynchronous-iteration'; 5 | 6 | // tag::020-asynchronous-generator-async-await[] 7 | const promiseList = [ 8 | randomTimeout(10, 1), 9 | randomTimeout(20, 2), 10 | randomTimeout(30, 3), 11 | ]; 12 | 13 | (async () => { 14 | for (const p of promiseList) { 15 | const res = await p; // <1> 16 | console.log(res); 17 | } 18 | })(); 19 | // end::020-asynchronous-generator-async-await[] 20 | export default promiseList; 21 | -------------------------------------------------------------------------------- /src/chapter15/030-simple-sync-generator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console */ 2 | import { 3 | randomTimeout, 4 | } from './010-asynchronous-iteration'; 5 | 6 | // tag::030-simple-sync-generator[] 7 | function* asyncGenerator() { // <1> 8 | yield randomTimeout(10, 1); // <2> 9 | console.log('First time'); 10 | yield randomTimeout(20, 2); 11 | console.log('Second time'); 12 | } 13 | 14 | const generator = asyncGenerator(); // <3> 15 | // prints '{ value: Promise { }, done: false }' 16 | console.log(generator.next()); 17 | // prints '{ value: Promise { }, done: false }' 18 | console.log(generator.next()); 19 | // prints '{ value: undefined, done: true }' 20 | console.log(generator.next()); 21 | 22 | for (const i of asyncGenerator()) { 23 | console.log(i); 24 | } 25 | 26 | (async () => { 27 | for (const p of asyncGenerator()) { 28 | const res = await p; 29 | console.log(res); 30 | } 31 | })(); 32 | // end::030-simple-sync-generator[] 33 | export default asyncGenerator; 34 | -------------------------------------------------------------------------------- /src/chapter15/050-simple-async-iterable-for-async-await.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable operator-linebreak, no-restricted-syntax */ 3 | import { 4 | FriendsService, 5 | } from './040-simple-async-iterable'; 6 | 7 | const result = 8 | // tag::050-simple-async-iterable-for-async-await[] 9 | (async () => { 10 | for await (const friend of new FriendsService()) { // <1> 11 | console.log(friend); 12 | } 13 | })(); 14 | // end::050-simple-async-iterable-for-async-await[] 15 | export default result; 16 | -------------------------------------------------------------------------------- /src/chapter15/060-simple-async-iterable-return.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-plusplus, semi, no-console */ 2 | /* eslint-disable no-restricted-syntax */ 3 | // tag::060-simple-async-iterable-return[] 4 | class SimpleIterable { 5 | constructor() { 6 | this.counter = 0; 7 | } 8 | 9 | [Symbol.asyncIterator]() { 10 | return { 11 | next: async () => { 12 | if (this.counter < 10) { 13 | this.counter++; 14 | return { value: this.counter, done: false }; 15 | } 16 | return { done: true }; 17 | }, 18 | async return() { // <1> 19 | console.log('Cleaning up'); 20 | return { done: true }; 21 | }, 22 | }; 23 | } 24 | } 25 | 26 | (async () => { 27 | try { 28 | for await (const n of new SimpleIterable()) { // <1> 29 | console.log(n); 30 | return; // <2> 31 | // or break, or throw new Error() 32 | } 33 | } catch (e) { 34 | console.log('Error', e); 35 | } 36 | })(); 37 | // end::060-simple-async-iterable-return[] 38 | export default SimpleIterable; 39 | -------------------------------------------------------------------------------- /src/chapter15/070-simple-async-iterable-try-catch.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable class-methods-use-this, semi, no-console */ 2 | /* eslint-disable no-restricted-syntax */ 3 | // tag::070-simple-async-iterable-try-catch[] 4 | class SimpleRejectingIterable { 5 | [Symbol.asyncIterator]() { 6 | return { 7 | next: () => Promise.reject(new Error('Error!')), // <1> 8 | }; 9 | } 10 | } 11 | 12 | (async () => { 13 | try { 14 | for await (const n of new SimpleRejectingIterable()) { 15 | // we will never get here 16 | console.log(n); 17 | } 18 | } catch (e) { 19 | console.log('Error', e); // <2> 20 | } 21 | })(); 22 | // end::070-simple-async-iterable-try-catch[] 23 | export default SimpleRejectingIterable; 24 | -------------------------------------------------------------------------------- /src/chapter15/080-for-await-of-sync-iterable.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console, no-restricted-syntax */ 2 | // tag::080-for-await-of-sync-iterable[] 3 | const randomTimeout = async (val, index) => { 4 | const timeout = Math.floor(Math.random() * Math.floor(42)); 5 | return new Promise(res => setTimeout(res, timeout, `My value is ${val} at index: ${index}`)); 6 | }; 7 | 8 | const promiseList = [ 9 | randomTimeout(10, 1), 10 | randomTimeout(20, 2), 11 | randomTimeout(30, 3), 12 | ]; // <1> 13 | 14 | (async () => { 15 | for await (const p of promiseList) { // <2> 16 | console.log(p); 17 | } 18 | })(); 19 | // end::080-for-await-of-sync-iterable[] 20 | export default promiseList; 21 | -------------------------------------------------------------------------------- /src/chapter15/090-aync-generator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax, no-console, prefer-destructuring, no-unused-vars */ 2 | /* eslint-disable no-unused-vars */ 3 | // tag::090-aync-generator[] 4 | const randomTimeout = async (val, index) => { 5 | const timeout = Math.floor(Math.random() * Math.floor(42)); 6 | return new Promise(res => setTimeout(res, timeout, `My value is ${val} at index: ${index}`)); 7 | }; 8 | 9 | async function* asyncGenerator() { // <1> 10 | yield await randomTimeout(10, 1); // <2> 11 | console.log('First time'); 12 | yield await randomTimeout(20, 2); 13 | console.log('Second time'); 14 | } 15 | 16 | console.log(typeof asyncGenerator()[Symbol.asyncIterator] === 'function'); 17 | 18 | (async () => { 19 | const gen = asyncGenerator(); 20 | for await (const item of gen) { // <3> 21 | console.log('item', item); 22 | } 23 | })(); 24 | // end::090-aync-generator[] 25 | export default asyncGenerator; 26 | -------------------------------------------------------------------------------- /src/chapter15/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /src/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "rules": { 6 | "import/no-extraneous-dependencies": [ 7 | "error", 8 | { 9 | "optionalDependencies": false, 10 | "peerDependencies": false 11 | } 12 | ], 13 | "no-unused-expressions": "off", 14 | "padded-blocks": "off" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/chapter01/030-var-overwritingSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import insiduous from '../../src/chapter01/030-var-overwriting'; 4 | 5 | describe('insiduous', () => { 6 | it('should return overwrite the outer declared value', () => { 7 | expect(insiduous()).to.be.equal('Inner declaration'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/chapter01/031-simulate-domSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import simulateDom from '../../src/chapter01/031-simulate-dom'; 4 | 5 | describe('simulateDom', () => { 6 | it('should define the function correctly', () => { 7 | expect(simulateDom).not.to.throw(); 8 | }); 9 | 10 | it('should define the same click handler for all elements', () => { 11 | const dom = simulateDom(); 12 | expect(dom.button1.click()).to.equal('Item 4 is clicked.'); 13 | expect(dom.button2.click()).to.equal('Item 4 is clicked.'); 14 | expect(dom.button3.click()).to.equal('Item 4 is clicked.'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chapter01/090-let-variablesSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import letFunction from '../../src/chapter01/090-let-variables'; 4 | 5 | describe('letFunction', () => { 6 | it('should not throw an error', () => { 7 | expect(letFunction).not.to.throw(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/chapter01/100-simulate-dom-with-letSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import simulateDom from '../../src/chapter01/100-simulate-dom-with-let'; 4 | 5 | describe('simulateDom', () => { 6 | it('should define the function correctly', () => { 7 | expect(simulateDom).not.to.throw(); 8 | }); 9 | 10 | it('should define the same click handler for all elements', () => { 11 | const dom = simulateDom(); 12 | expect(dom.button1.click()).to.equal('Item 1 is clicked.'); 13 | expect(dom.button2.click()).to.equal('Item 2 is clicked.'); 14 | expect(dom.button3.click()).to.equal('Item 3 is clicked.'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chapter01/110-lets-hoistingSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import foo from '../../src/chapter01/110-let-hoisted'; 4 | 5 | describe('foo', () => { 6 | it('should not throw an error', () => { 7 | expect(foo).not.to.throw(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/chapter01/120-let-and-switchSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-eval */ 2 | 3 | import { 4 | expect, 5 | } from 'chai'; 6 | 7 | const fs = require('fs'); 8 | 9 | describe('createBadFunction', () => { 10 | it('should return throw an error', (done) => { 11 | fs.readFile('./src/chapter01/120-let-and-switch.js', (err, data) => { 12 | if (err) { 13 | // we expect an error 14 | expect(true).to.equal(false); 15 | } 16 | try { 17 | eval(data.toString()); 18 | // should never get here 19 | expect(true).to.equal(false); 20 | done(); 21 | } catch (e) { 22 | expect(e.message).to.equal('Identifier \'drink\' has already been declared'); 23 | done(); 24 | } 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter01/130-iefe-for-varSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import counter from '../../src/chapter01/130-iefe-for-var'; 4 | 5 | describe('IEFE counter', () => { 6 | it('should return a counter', () => { 7 | expect(counter).to.exist; 8 | }); 9 | 10 | it('should have 1 steps', () => { 11 | expect(counter.getCount()).to.equal(1); 12 | }); 13 | 14 | it('should have increment steps', () => { 15 | counter.increment(); 16 | // we invoke it once in the actual code, so here we are starting at 1 17 | expect(counter.getCount()).to.equal(2); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter01/140-eliminate-iefe-with-letSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import counter from '../../src/chapter01/140-eliminate-iefe-with-let'; 4 | 5 | describe('Block-let counter', () => { 6 | it('should return a counter', () => { 7 | expect(counter).to.exist; 8 | }); 9 | 10 | it('should have 1 steps', () => { 11 | expect(counter.getCount()).to.equal(1); 12 | }); 13 | 14 | it('should have increment steps', () => { 15 | counter.increment(); 16 | // we invoke it once in the actual code, so here we are starting at 1 17 | expect(counter.getCount()).to.equal(2); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter01/150-const-reference-cannot-changeSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-destructuring */ 2 | import { 3 | expect, 4 | } from 'chai'; 5 | 6 | import { 7 | VALUE_REFERENCE, 8 | ARRAY_REFERENCE, 9 | } from '../../src/chapter01/150-const-reference-cannot-change'; 10 | 11 | describe('const references', () => { 12 | describe('VALUE_REFERENCE', () => { 13 | it('should export it', () => { 14 | expect(VALUE_REFERENCE).to.exist; 15 | }); 16 | }); 17 | 18 | describe('ARRAY_REFERENCE', () => { 19 | it('should export it', () => { 20 | expect(ARRAY_REFERENCE).not.to.be.empty; 21 | }); 22 | 23 | it('should allow mutation', () => { 24 | const length = ARRAY_REFERENCE.length; 25 | ARRAY_REFERENCE.push('!'); 26 | expect(ARRAY_REFERENCE.length).to.equal(length + 1); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/chapter01/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter02/010-function-statementSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import identity from '../../src/chapter02/010-function-statement'; 6 | 7 | describe('identity statement', () => { 8 | it('should not throw an error', () => { 9 | expect(identity).to.be.a('function'); 10 | }); 11 | 12 | it('should be the identity function', () => { 13 | expect(identity(2)).to.be.equal(2); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/020-function-expressionSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import identity from '../../src/chapter02/020-function-expression'; 6 | 7 | describe('identity expression', () => { 8 | it('should not throw an error', () => { 9 | expect(identity).to.be.a('function'); 10 | }); 11 | 12 | it('should be the identity function', () => { 13 | expect(identity(2)).to.be.equal(2); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/025-function-statement-vs-expressionSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | fnStatement, 7 | fnExpression, 8 | } from '../../src/chapter02/025-function-statement-vs-expression'; 9 | 10 | describe('025-function-statement-vs-expression', () => { 11 | it('should not throw an error', () => { 12 | expect(fnStatement).to.be.a('function'); 13 | expect(fnExpression).to.be.a('function'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/030-arrays-manipulation-with-function-expressionSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import arrayManipulation from '../../src/chapter02/030-arrays-manipulation-with-function-expression'; 6 | 7 | describe('arrayManipulation', () => { 8 | it('should not throw an error', () => { 9 | expect(arrayManipulation).to.be.a('function'); 10 | }); 11 | 12 | it('should return the doubled average', () => { 13 | expect(arrayManipulation()).to.be.equal(18); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/040-fat-arrow-syntaxSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import doubleIt from '../../src/chapter02/040-fat-arrow-syntax'; 6 | 7 | describe('doubleIt', () => { 8 | it('should not throw an error', () => { 9 | expect(doubleIt).to.be.a('function'); 10 | }); 11 | 12 | it('should return the doubled average', () => { 13 | expect(doubleIt(8)).to.be.equal(16); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/050-arrow-parametersSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | noop, 7 | identity, 8 | get, 9 | } from '../../src/chapter02/050-arrow-parameters'; 10 | 11 | describe('arrow params', () => { 12 | it('should return define all the functions', () => { 13 | expect(noop).to.be.a('function'); 14 | expect(identity).to.be.a('function'); 15 | expect(get).to.be.a('function'); 16 | }); 17 | 18 | it('should do what we expect', () => { 19 | expect(noop()).not.be.ok; 20 | expect(identity(16)).to.be.equal(16); 21 | expect(get({ 22 | name: 'raju', 23 | }, 'name')).to.be.equal('raju'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/chapter02/060-arrow-block-bodySpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import reducer from '../../src/chapter02/060-arrow-block-body'; 6 | 7 | describe('arrow block body', () => { 8 | it('should return define all the functions', () => { 9 | expect(reducer).to.be.a('function'); 10 | }); 11 | 12 | it('should push on to array', () => { 13 | expect(reducer([2, 3], 1)).to.eql([2, 3, 1]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/070-arrow-block-confusingSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import confuser from '../../src/chapter02/070-arrow-block-confusing'; 6 | 7 | describe('arrow single line block body', () => { 8 | it('should define the confuser', () => { 9 | expect(confuser).to.be.a('function'); 10 | }); 11 | 12 | it('should return undefined', () => { 13 | expect(confuser()).not.be.ok; 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/080-arrow-block-parenthesisSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | confuserOne, 7 | confuserTwo, 8 | } from '../../src/chapter02/080-arrow-block-parenthesis'; 9 | 10 | describe('arrow single line block body', () => { 11 | it('should define the confuser', () => { 12 | expect(confuserOne).to.be.a('function'); 13 | expect(confuserTwo).to.be.a('function'); 14 | }); 15 | 16 | it('should return an object', () => { 17 | expect(confuserOne()).to.eql({ profession: 'JS Ninja' }); 18 | expect(confuserTwo()).to.eql({ profession: 'JS Ninja' }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter02/090-function-expression-invocation-patternsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import returnsThis from '../../src/chapter02/090-function-expression-invocation-patterns'; 6 | 7 | describe('function expression invocation pattern', () => { 8 | it('should define the returnMe function', () => { 9 | expect(returnsThis).to.be.a('function'); 10 | }); 11 | 12 | it('function invocation should return undefined', () => { 13 | expect(returnsThis()).to.be.undefined; 14 | }); 15 | 16 | it('method invocation should return the object', () => { 17 | const obj = { 18 | m: returnsThis, 19 | }; 20 | expect(obj.m()).to.equal(obj); 21 | }); 22 | 23 | it('call invocation should return the object', () => { 24 | const obj = { 25 | }; 26 | expect(returnsThis.apply(obj)).to.equal(obj); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/chapter02/120-arrow-expression-and-thisSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | GLOBAL_OBJECT, 7 | returnMe, 8 | } from '../../src/chapter02/120-arrow-expression-and-this'; 9 | 10 | describe('arrow functions', () => { 11 | it('should define the returnMe function', () => { 12 | expect(returnMe).to.be.a('function'); 13 | }); 14 | 15 | it('function invocation should return GLOBAL_OBJECT', () => { 16 | expect(returnMe()).to.equal(GLOBAL_OBJECT); 17 | }); 18 | 19 | it('method invocation should return GLOBAL_OBJECT', () => { 20 | const obj = { 21 | m: returnMe, 22 | }; 23 | expect(obj.m()).to.equal(GLOBAL_OBJECT); 24 | }); 25 | 26 | it('call invocation should return GLOBAL_OBJECT', () => { 27 | const obj = { 28 | }; 29 | expect(returnMe.apply(obj)).to.equal(GLOBAL_OBJECT); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/chapter02/130-arrays-manipulation-with-arrow-functionsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import arrayManipulation from '../../src/chapter02/130-arrays-manipulation-with-arrow-functions'; 6 | 7 | describe('arrayManipulation', () => { 8 | it('should not throw an error', () => { 9 | expect(arrayManipulation).to.be.a('function'); 10 | }); 11 | 12 | it('should return the doubled average', () => { 13 | expect(arrayManipulation()).to.be.equal(18); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter02/140-knowing-what-this-arrow-functionsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import neo from '../../src/chapter02/140-knowing-what-this-arrow-functions'; 6 | 7 | describe('neo', () => { 8 | it('should be an object', () => { 9 | expect(neo).to.be.a('object'); 10 | expect(neo.friends).to.be.an('array'); 11 | }); 12 | 13 | it('should add new friends', () => { 14 | neo.addFriends('Michelle', 'Mason'); 15 | expect(neo.friends).to.be.eql([ 16 | 'Morpheus', 17 | 'Brian', 18 | 'Switch', 19 | 'Niobe', 20 | 'Tank', 21 | 'Michelle', 22 | 'Mason', 23 | ]); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/chapter02/150-make-and-using-arrow-functionsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import and from '../../src/chapter02/150-make-and-using-arrow-functions'; 6 | 7 | describe('and', () => { 8 | let gt10; 9 | let even; 10 | let evenAndGt10; 11 | 12 | beforeEach(() => { 13 | gt10 = n => n > 10; 14 | even = n => n % 2 === 0; 15 | evenAndGt10 = and(gt10, even); 16 | }); 17 | 18 | it('should be an object', () => { 19 | expect(and).to.be.a('function'); 20 | }); 21 | 22 | it('should define a new function', () => { 23 | expect(evenAndGt10).to.be.a('function'); 24 | }); 25 | 26 | it('should apply and predicates', () => { 27 | expect(evenAndGt10(15)).to.equal(false); 28 | expect(evenAndGt10(22)).to.equal(true); 29 | expect(evenAndGt10(2)).to.equal(false); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/chapter02/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter03/010-function-multi-aritySpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | add, 7 | sayHello, 8 | buildUrl, 9 | } from '../../src/chapter03/010-function-multi-arity'; 10 | 11 | describe('010-function-multi-arity', () => { 12 | it('should define all the functions', () => { 13 | expect(add).to.be.a('function'); 14 | expect(sayHello).to.be.a('function'); 15 | expect(buildUrl).to.be.a('function'); 16 | }); 17 | 18 | it('add should add all the numbers', () => { 19 | expect(add(5, 4, -1)).to.be.equal(8); 20 | }); 21 | 22 | it('sayHello should greet me', () => { 23 | expect(sayHello('raju')).to.be.equal('Hello raju'); 24 | }); 25 | 26 | it('build url should return a new url', () => { 27 | expect(buildUrl('www.example.com', 'http')) 28 | .to.be.equal('http://www.example.com'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/chapter03/020-function-default-checksSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import buildUrl from '../../src/chapter03/020-function-default-checks'; 6 | 7 | describe('default checks', () => { 8 | it('should define all the functions', () => { 9 | expect(buildUrl).to.be.a('function'); 10 | }); 11 | 12 | describe('buildUrl', () => { 13 | it('should return a new url', () => { 14 | expect(buildUrl('www.example.com', 'http')) 15 | .to.be.equal('http://www.example.com'); 16 | }); 17 | 18 | it('should default protocol', () => { 19 | expect(buildUrl('www.example.com')) 20 | .to.be.equal('http://www.example.com'); 21 | }); 22 | 23 | it('should error if site is not passed', () => { 24 | expect(() => buildUrl()).to.throw(); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter03/030-function-default-argsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import buildUrl from '../../src/chapter03/030-function-default-args'; 6 | 7 | describe('default checks', () => { 8 | it('should define all the functions', () => { 9 | expect(buildUrl).to.be.a('function'); 10 | }); 11 | 12 | describe('buildUrl', () => { 13 | it('should return a new url', () => { 14 | expect(buildUrl('www.example.com', 'http')) 15 | .to.be.equal('http://www.example.com'); 16 | }); 17 | 18 | it('should default protocol', () => { 19 | expect(buildUrl('www.example.com', 'http')) 20 | .to.be.equal('http://www.example.com'); 21 | }); 22 | 23 | it('should error if site is not passed', () => { 24 | expect(() => buildUrl()).to.throw(); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter03/040-expression-default-paramSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | getDefaultConn, 7 | query, 8 | } from '../../src/chapter03/040-expression-default-param'; 9 | 10 | describe('expression as defaults', () => { 11 | it('should define all the functions', () => { 12 | expect(getDefaultConn).to.be.a('function'); 13 | expect(query).to.be.a('function'); 14 | }); 15 | 16 | describe('getDefaultConn', () => { 17 | it('should return a new obj', () => { 18 | expect(getDefaultConn()).to.be.a('object'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter03/050-rectangleSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import rectangle from '../../src/chapter03/050-rectangle'; 6 | 7 | describe('rectangle', () => { 8 | it('should define all the functions', () => { 9 | expect(rectangle).to.be.a('function'); 10 | }); 11 | 12 | it('should create rectangles', () => { 13 | expect(rectangle(2, 3)).to.be.eql([2, 3]); 14 | expect(rectangle(2)).to.be.eql([2, 2]); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chapter03/060-triangleSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import triangle from '../../src/chapter03/060-triangle'; 6 | 7 | describe('triangle', () => { 8 | it('should define all the functions', () => { 9 | expect(triangle).to.be.a('function'); 10 | }); 11 | 12 | it('should create triangles', () => { 13 | expect(triangle(6, 4)).to.be.eql([6, 4, Math.hypot(6, 4)]); 14 | expect(triangle(10)).to.be.eql([10, 10, Math.hypot(10, 10)]); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chapter03/080-default-before-requiredSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import filter from '../../src/chapter03/080-default-before-required'; 6 | 7 | describe('filter', () => { 8 | it('should define all the functions', () => { 9 | expect(filter).to.be.a('function'); 10 | }); 11 | 12 | it('should return the length of the args', () => { 13 | expect(filter([1, 2, 3], n => n > 2)).to.be.eql([3]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter03/090-using-argumentsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import add from '../../src/chapter03/090-using-arguments'; 6 | 7 | describe('using arguments', () => { 8 | it('should define the add function', () => { 9 | expect(add).to.be.a('function'); 10 | }); 11 | 12 | it('add should add all the numbers', () => { 13 | expect(add(5, 4, -1)).to.be.equal(8); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter03/120-rest-params-lengthSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | fnExpression, 7 | fnArrow, 8 | } from '../../src/chapter03/120-rest-params-length'; 9 | 10 | describe('rest params length property', () => { 11 | it('should define all the functions', () => { 12 | expect(fnExpression).to.be.a('function'); 13 | expect(fnArrow).to.be.a('function'); 14 | }); 15 | 16 | it('should have the right lengths', () => { 17 | expect(fnExpression.length).to.be.equal(2); 18 | expect(fnArrow.length).to.be.equal(2); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter03/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter04/010-convoluted-lookupSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import convolutedLookup from '../../src/chapter04/010-convoluted-lookup'; 6 | 7 | describe('110-rest-params-instead-of-arguments', () => { 8 | it('should define all the functions', () => { 9 | expect(convolutedLookup).to.be.a('function'); 10 | }); 11 | 12 | it('convolutedLookup should do the right thing', () => { 13 | const [z1, z2] = convolutedLookup(); 14 | expect(z1).to.be.equal('95014-1234'); 15 | expect(z2).to.be.equal('95014-1234'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter04/020-perimeter-applySpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import perimeter from '../../src/chapter04/020-perimeter-apply'; 6 | 7 | describe('020-perimeter-apply', () => { 8 | it('should define all the functions', () => { 9 | expect(perimeter).to.be.a('function'); 10 | }); 11 | 12 | it('perimeter should do the right thing', () => { 13 | const p = perimeter(9, 8, 3); 14 | expect(p).to.be.equal(20); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chapter04/030-perimeter-spreadSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import perimeter from '../../src/chapter04/030-perimeter-spread'; 6 | 7 | describe('030-perimeter-spread', () => { 8 | it('should define all the functions', () => { 9 | expect(perimeter).to.be.a('function'); 10 | }); 11 | 12 | it('perimeter should do the right thing', () => { 13 | const p = perimeter(9, 8, 3); 14 | expect(p).to.be.equal(20); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chapter04/040-spread-console-logSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import printIt from '../../src/chapter04/040-spread-console-log'; 6 | 7 | describe('040-spread-console-log', () => { 8 | it('should define all the functions', () => { 9 | expect(printIt).to.be.a('function'); 10 | }); 11 | 12 | it('printIt to console should print as expected', () => { 13 | const [arr, str] = printIt(); 14 | expect(arr).to.be.eql([12, -3, 15, 44, 15, 36]); 15 | expect(str).to.be.equal('12 -3 15 44 15 36'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter04/050-spread-create-concatenate-arraysSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import createAndConcatenate from '../../src/chapter04/050-spread-create-concatenate-arrays'; 6 | 7 | describe('050-spread-create-concatenate-arrays', () => { 8 | it('should define all the functions', () => { 9 | expect(createAndConcatenate).to.be.a('function'); 10 | }); 11 | 12 | it('createAndConcatenate should do the right thing', () => { 13 | const [one, two, three] = createAndConcatenate(); 14 | expect(one).to.be.eql([12, -3, 15, 44, 15, 36]); 15 | expect(two).to.be.eql([12, -3, 15, 44, 15, 36]); 16 | expect(three).to.be.eql([12, -3, 15, 44, 15, 36]); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter04/060-spread-rest-togetherSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | onlyRest, 7 | restAndSpread, 8 | } from '../../src/chapter04/060-spread-rest-together'; 9 | 10 | describe('060-spread-rest-together', () => { 11 | 12 | it('should define all the functions', () => { 13 | expect(onlyRest).to.be.a('function'); 14 | expect(restAndSpread).to.be.a('function'); 15 | }); 16 | 17 | it('onlyRest should return an array of arrays', () => { 18 | const ret = onlyRest('Venkat', 'Raju', 'Daniel', 'Jonathan'); 19 | expect(ret).to.eql(['Venkat', ['Daniel', 'Jonathan', 'Raju']]); 20 | }); 21 | 22 | it('restAndSpread should return an array of arrays', () => { 23 | const ret = restAndSpread('Venkat', 'Raju', 'Daniel', 'Jonathan'); 24 | expect(ret).to.eql(['Venkat', 'Daniel', 'Jonathan', 'Raju']); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/chapter04/065-object-api-defineProperties-enumerableSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import michelle from '../../src/chapter04/065-object-api-defineProperties-enumerable'; 6 | 7 | describe('chapter06', () => { 8 | describe('065-object-api-defineProperties-enumerable', () => { 9 | it('should define all the objects', () => { 10 | expect(michelle).to.be.a('object'); 11 | }); 12 | 13 | it('should define the properties correctly for michelle', () => { 14 | expect(michelle.name).to.be.equal('Michelle'); 15 | expect(michelle.hobby).to.be.equal('Gardening'); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter04/067-object-api-defineProperties-enumerableSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import michelle from '../../src/chapter04/067-object-api-defineProperties-enumerable'; 6 | 7 | describe('chapter06', () => { 8 | describe('067-object-api-defineProperties-enumerable', () => { 9 | it('should define all the objects', () => { 10 | expect(michelle).to.be.a('object'); 11 | }); 12 | 13 | it('should define the name property correctly for michelle', () => { 14 | expect(michelle.name).to.be.equal('Michelle'); 15 | expect(Object.prototype.hasOwnProperty.call(michelle, 'name')).to.be.equal(true); 16 | }); 17 | 18 | it('should define the hobby property correctly for michelle', () => { 19 | expect(michelle.hobby).to.be.equal('Gardening'); 20 | expect(Object.prototype.propertyIsEnumerable.call(michelle, 'hobby')).to.be.equal(false); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter04/068-object-assignSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import rachael from '../../src/chapter04/068-object-assign'; 6 | 7 | describe('chapter06', () => { 8 | describe('068-object-assign', () => { 9 | it('should define all the objects', () => { 10 | expect(rachael).to.be.a('object'); 11 | }); 12 | 13 | it('should greet the invokee', () => { 14 | expect(rachael.name).to.be.equal('Rachael'); 15 | expect(rachael.hobby).to.be.equal('Gardening'); 16 | expect(rachael.profession).to.be.equal('Auditor'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter04/069-object-spreadSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import rachael from '../../src/chapter04/069-object-spread'; 6 | 7 | describe('chapter06', () => { 8 | describe('069-object-spread', () => { 9 | it('should define all the objects', () => { 10 | expect(rachael).to.be.a('object'); 11 | }); 12 | 13 | it('should greet the invokee', () => { 14 | expect(rachael.name).to.be.equal('Rachael'); 15 | expect(rachael.hobby).to.be.equal('Gardening'); 16 | expect(rachael.profession).to.be.equal('Auditor'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter04/070-array-destructuringSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | r, 7 | g, 8 | b, 9 | a, 10 | nonExistent, 11 | blue, 12 | blueAgain, 13 | } from '../../src/chapter04/070-array-destructuring'; 14 | 15 | describe('070-array-destructuring', () => { 16 | it('should define all variables', () => { 17 | expect(r).to.be.a('number'); 18 | expect(g).to.be.a('number'); 19 | expect(b).to.be.a('number'); 20 | expect(a).to.be.a('number'); 21 | expect(nonExistent).not.to.be.ok; 22 | expect(blue).to.be.a('number'); 23 | }); 24 | 25 | it('should set the right values', () => { 26 | // 239, 15, 255, 0.9 27 | expect(r).to.be.equal(239); 28 | expect(g).to.be.equal(15); 29 | expect(b).to.be.equal(255); 30 | expect(a).to.be.equal(0.9); 31 | expect(blue).to.be.equal(b); 32 | expect(blueAgain).to.be.equal(b); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/chapter04/090-array-destructuring-function-parameterSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import perimeter from '../../src/chapter04/090-array-destructuring-function-parameter'; 6 | 7 | describe('090-array-destructuring-function-parameter', () => { 8 | it('should define all functions', () => { 9 | expect(perimeter).to.be.a('function'); 10 | }); 11 | 12 | it('should calculate perimeter correctly', () => { 13 | expect(perimeter()).to.be.equal(40); 14 | expect(perimeter([])).to.be.equal(40); 15 | expect(perimeter([15])).to.be.equal(60); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter04/100-array-destructuring-restSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | movies, 7 | first, 8 | rest, 9 | head, 10 | tail, 11 | } from '../../src/chapter04/100-array-destructuring-rest'; 12 | 13 | describe('100-array-destructuring-rest', () => { 14 | it('should define all variables', () => { 15 | expect(movies).to.be.a('array'); 16 | expect(first).to.be.a('string'); 17 | expect(rest).to.be.a('array'); 18 | expect(head).to.be.a('string'); 19 | expect(tail).to.be.a('array'); 20 | }); 21 | 22 | it('should the right thing', () => { 23 | expect(movies).to.be.eql(['Momento', 'Batman Begins', 'The Dark Knight']); 24 | expect(first).to.be.equal('Momento'); 25 | expect(rest).to.be.eql(['Batman Begins', 'The Dark Knight']); 26 | expect(head).to.be.equal('Batman Begins'); 27 | expect(tail).to.be.eql(['The Dark Knight']); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/chapter04/110-recursive-orSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import or from '../../src/chapter04/110-recursive-or'; 6 | 7 | describe('110-recursive-or', () => { 8 | it('should define all function', () => { 9 | expect(or).to.be.a('function'); 10 | }); 11 | 12 | it('should return truthy for even a single truthy', () => { 13 | const val = or(true, false); 14 | expect(val).to.be.ok; 15 | expect(val).to.be.equal(true); 16 | }); 17 | 18 | it('should return falsey for ALL falseys', () => { 19 | const val = or(undefined, false, null, 0); 20 | expect(val).not.to.be.ok; 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/chapter04/120-array-nested-destructuringSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | ticTacToe, 7 | cell01, 8 | cell11, 9 | cell22, 10 | } from '../../src/chapter04/120-array-nested-destructuring'; 11 | 12 | describe('111-array-nested-destructuring', () => { 13 | it('should define all variable', () => { 14 | expect(ticTacToe).to.be.a('array'); 15 | expect(cell01).to.be.a('string'); 16 | expect(cell11).to.be.a('string'); 17 | expect(cell22).to.be.a('string'); 18 | }); 19 | 20 | it('should extract the correct values', () => { 21 | expect(cell01).to.be.equal('x'); 22 | expect(cell11).to.be.equal('x'); 23 | expect(cell22).to.be.equal('x'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/chapter04/121-multiple-returnsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import flatten from '../../src/chapter04/125-destruct-rest-params'; 6 | 7 | describe('125-destruct-rest-params', () => { 8 | it('should define all functions', () => { 9 | expect(flatten).to.be.a('function'); 10 | }); 11 | 12 | it('should flatten an array', () => { 13 | const result = flatten([ 14 | [1, 2], 15 | [3], 4, 5, [6, 7], 16 | ]); 17 | expect(result).to.be.eql([1, 2, 3, 4, 5, 6, 7]); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter04/125-destruct-rest-paramsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import distanceAndSlope from '../../src/chapter04/121-multiple-returns'; 6 | 7 | describe('121-multiple-returns', () => { 8 | it('should define all functions', () => { 9 | expect(distanceAndSlope).to.be.a('function'); 10 | }); 11 | 12 | it('should extract the correct values', () => { 13 | const [d, s] = distanceAndSlope([15, 2], [5, 9]); 14 | expect(Number.parseFloat(d.toFixed(2))).to.be.equal(12.21); 15 | expect(s).to.be.equal(-0.7); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter04/130-object-destructuringSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import * as obj from '../../src/chapter04/130-object-destructuring'; 6 | 7 | describe('130-object-destructuring', () => { 8 | it('should define all variables', () => { 9 | expect(obj.paip).to.be.a('object'); 10 | expect(obj.n).to.be.a('string'); 11 | expect(obj.id).to.be.a('number'); 12 | expect(obj.name).to.be.a('string'); 13 | expect(obj.isbn).to.be.a('number'); 14 | }); 15 | 16 | it('should set the right values', () => { 17 | // 239, 15, 255, 0.9 18 | expect(obj.n).to.be.equal(obj.paip.name); 19 | expect(obj.id).to.be.equal(obj.paip.isbn); 20 | expect(obj.name).to.be.equal(obj.paip.name); 21 | expect(obj.isbn).to.be.equal(obj.paip.isbn); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter04/150-convoluted-lookup-with-destructuringSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import final from '../../src/chapter04/150-convoluted-lookup-with-destructuring'; 6 | 7 | describe('150-convoluted-lookup-with-destructuring', () => { 8 | it('should define all the functions', () => { 9 | expect(final).to.be.a('string'); 10 | }); 11 | 12 | it('should look up the zip code', () => { 13 | expect(final).to.be.equal('95014-1234'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter04/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter05/005-interpolationSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import fullName from '../../src/chapter05/005-interpolation'; 4 | 5 | describe('chapter05', () => { 6 | describe('005-interpolation', () => { 7 | it('should define all the objects', () => { 8 | expect(fullName).not.to.be.undefined; 9 | }); 10 | 11 | it('should correctly define the message', () => { 12 | expect(fullName).to.be.equal('Mr. Edgar Allen Poe'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter05/010-simple-template-literalSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import msg from '../../src/chapter05/010-simple-template-literal'; 4 | 5 | describe('chapter05', () => { 6 | describe('010-simple-template-literal', () => { 7 | it('should define all the objects', () => { 8 | expect(msg).not.to.be.undefined; 9 | }); 10 | 11 | it('should correctly define the message', () => { 12 | expect(msg).to.be.equal('Hola! My name is Daniel'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter05/020-nested-interpolationSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import msg from '../../src/chapter05/020-nested-interpolation'; 4 | 5 | describe('chapter05', () => { 6 | xdescribe('020-nested-interpolation', () => { 7 | it('should define all the objects', () => { 8 | expect(msg).not.to.be.undefined; 9 | }); 10 | 11 | it('should correctly define the message', () => { 12 | expect(msg).to.be.equal('Hola! My name is Daniel'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter05/030-escaping-literalsSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import escapingLiterals from '../../src/chapter05/030-escaping-literals'; 4 | 5 | describe('chapter05', () => { 6 | describe('030-escaping-literals', () => { 7 | it('should define all the objects', () => { 8 | expect(escapingLiterals).not.to.be.undefined; 9 | }); 10 | 11 | it('should correctly define the message', () => { 12 | expect(escapingLiterals).to.be.equal('Template strings introduce `` and use ${} for interpolation'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter05/040-static-vs-dynamicSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { 4 | msg, 5 | greeting, 6 | name, 7 | fixedStrings, 8 | values, 9 | } from '../../src/chapter05/040-static-vs-dynamic'; 10 | 11 | describe('chapter05', () => { 12 | describe('040-static-vs-dynamic', () => { 13 | it('should define all the objects', () => { 14 | expect(msg).not.to.be.undefined; 15 | expect(fixedStrings).not.to.be.undefined; 16 | expect(values).not.to.be.undefined; 17 | }); 18 | 19 | it('should correctly fixed and dynamic parts', () => { 20 | const handler = (strings, ...v) => { 21 | expect(fixedStrings).to.eql(strings); 22 | expect(values).to.eql(v); 23 | }; 24 | 25 | handler`${greeting}! My name is ${name}!`; 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/chapter05/050-reimplement-template-stringsSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { 4 | handler, 5 | greeting, 6 | name, 7 | msg, 8 | } from '../../src/chapter05/050-reimplement-template-strings'; 9 | 10 | describe('chapter05', () => { 11 | describe('050-reimplement-template-strings', () => { 12 | it('should define all the objects', () => { 13 | expect(handler).not.to.be.undefined; 14 | expect(greeting).not.to.be.undefined; 15 | expect(name).not.to.be.undefined; 16 | expect(msg).not.to.be.undefined; 17 | }); 18 | 19 | it('should correctly fixed and dynamic parts', () => { 20 | const g = 'Hola'; 21 | const n = 'Danno'; 22 | const x = handler`${g}! My name is ${n}!`; 23 | expect(x).to.be.equal('Hola! My name is Danno!'); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/chapter05/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter06/010-objects-keys-stringsSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable dot-notation */ 2 | 3 | import { 4 | expect, 5 | } from 'chai'; 6 | 7 | import * as example010 from '../../src/chapter06/010-objects-keys-strings'; 8 | 9 | describe('chapter06', () => { 10 | describe('010-objects-keys-strings', () => { 11 | it('should define all the objects', () => { 12 | expect(example010.obj1).to.be.a('object'); 13 | expect(example010.obj2).to.be.a('object'); 14 | }); 15 | 16 | it('should have the appropriate keys set', () => { 17 | expect(example010.obj1[true]).to.be.equal('Boolean'); 18 | expect(example010.obj2[true]).to.be.equal('String'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter06/020-maps-construction-manipulationSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import * as example020 from '../../src/chapter06/020-maps-construction-manipulation'; 6 | 7 | describe('chapter06', () => { 8 | describe('020-maps-construction-manipulation', () => { 9 | it('should define all the objects', () => { 10 | expect(example020.map).to.be.a('map'); 11 | }); 12 | 13 | it('should have the appropriate keys set', () => { 14 | expect(example020.map.get(true)).to.be.equal('is a boolean'); 15 | expect(example020.map.get(1)).to.be.equal('overrides first'); 16 | expect(example020.map.get(example020.obj)).to.be.equal('is an object'); 17 | 18 | expect(example020.map.get('string')).not.to.be.ok; 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter06/030-maps-whole-manipulationSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import map from '../../src/chapter06/030-maps-whole-manipulation'; 6 | 7 | describe('chapter06', () => { 8 | describe('030-maps-whole-manipulation', () => { 9 | it('should define all the objects', () => { 10 | expect(map).to.be.a('map'); 11 | }); 12 | 13 | it('should have cleared the keys', () => { 14 | expect(map.size).to.be.equal(0); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter06/040-spreading-mapsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import firstQuarter from '../../src/chapter06/040-spreading-maps'; 6 | 7 | describe('chapter06', () => { 8 | describe('040-spreading-maps', () => { 9 | it('should define all the objects', () => { 10 | expect(firstQuarter).to.be.a('map'); 11 | }); 12 | 13 | it('should be spreadable', () => { 14 | const toStr = [...firstQuarter].join(':'); 15 | expect(toStr).to.be.equal('1,Jan:2,Feb:3,Mar:4,Apr'); 16 | }); 17 | 18 | it('should be destructurable', () => { 19 | const [, , , [n, m]] = firstQuarter; 20 | expect(n).to.be.equal(4); 21 | expect(m).to.be.equal('Apr'); 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/chapter06/050-maps-from-other-mapsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import union from '../../src/chapter06/050-maps-from-other-maps'; 6 | 7 | describe('chapter06', () => { 8 | describe('050-maps-from-other-maps', () => { 9 | it('should define all the objects', () => { 10 | expect(union).to.be.a('map'); 11 | }); 12 | 13 | it('should have the right size', () => { 14 | expect(union.size).to.be.equal(3); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter06/055-no-literals-for-mapsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | kiran, 7 | favFruits, 8 | numbersInHindi, 9 | } from '../../src/chapter06/055-no-literals-for-maps'; 10 | 11 | describe('chapter06', () => { 12 | describe('055-no-literals-for-maps', () => { 13 | it('should define all the objects', () => { 14 | expect(kiran).to.be.a('object'); 15 | expect(favFruits).to.be.a('array'); 16 | expect(numbersInHindi).to.be.a('map'); 17 | }); 18 | 19 | it('should have the right attributes', () => { 20 | expect(kiran.name).to.be.equal('kiran'); 21 | expect(favFruits.length).to.be.equal(3); 22 | expect(numbersInHindi.get(3)).to.be.equal('teen'); 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/chapter06/060-maps-to-from-jsonSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import * as toJson from '../../src/chapter06/060-maps-to-from-json'; 6 | 7 | describe('chapter06', () => { 8 | describe('060-maps-to-from-json', () => { 9 | it('should define all the objects', () => { 10 | expect(toJson.nihar).to.be.a('map'); 11 | expect(toJson.serialized).to.be.a('string'); 12 | expect(toJson.deserialized).to.be.a('map'); 13 | }); 14 | 15 | it('should be serialize correctly', () => { 16 | expect(toJson.serialized).to.be.equal('[["car","mazda"],["residence","apartment"]]'); 17 | }); 18 | 19 | it('should be deserialize correctly', () => { 20 | expect(toJson.deserialized).to.be.eql(toJson.nihar); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter06/070-maps-to-from-json-failSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import * as toJson from '../../src/chapter06/070-maps-to-from-json-fail'; 6 | 7 | describe('chapter06', () => { 8 | describe('070-maps-to-from-json-fail', () => { 9 | it('should define all the objects', () => { 10 | expect(toJson.map).to.be.a('map'); 11 | expect(toJson.serialized).to.be.a('string'); 12 | expect(toJson.deserialized).to.be.a('map'); 13 | }); 14 | 15 | it('should be serialize correctly', () => { 16 | expect(toJson.serialized).to.be.equal('[[{"name":"some object"},"value against an object key"]]'); 17 | }); 18 | 19 | it('should be deserialize correctly', () => { 20 | expect(toJson.deserialized).to.be.eql(toJson.map); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter06/080-maps-hard-referencesSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import * as hardRef from '../../src/chapter06/080-maps-hard-references'; 6 | 7 | describe('chapter06', () => { 8 | describe('080-maps-hard-references', () => { 9 | it('should define all the objects', () => { 10 | expect(hardRef.obj).not.to.be.ok; 11 | expect(hardRef.map).to.be.a('map'); 12 | }); 13 | 14 | it('should contain the key reference', () => { 15 | expect(hardRef.map.size).to.be.equal(1); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter06/090-sets-construction-manipulationSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import * as example090 from '../../src/chapter06/090-sets-construction-manipulation'; 6 | 7 | describe('chapter06', () => { 8 | describe('090-sets-construction-manipulation', () => { 9 | it('should define all the objects', () => { 10 | expect(example090.set).to.be.a('set'); 11 | }); 12 | 13 | it('should have the appropriate keys set', () => { 14 | expect(example090.set.has(true)).to.be.equal(true); 15 | expect(example090.set.has(1)).to.be.equal(true); 16 | expect(example090.set.has(example090.obj)).to.be.equal(true); 17 | 18 | expect(example090.set.has('string')).not.to.be.ok; 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter06/100-sets-whole-manipulationSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import set from '../../src/chapter06/100-sets-whole-manipulation'; 6 | 7 | describe('chapter06', () => { 8 | describe('100-sets-whole-manipulation', () => { 9 | it('should define all the objects', () => { 10 | expect(set).to.be.a('set'); 11 | }); 12 | 13 | it('should have cleared the keys', () => { 14 | expect(set.size).to.be.equal(0); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter06/110-sets-from-other-setSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import union from '../../src/chapter06/110-sets-from-other-set'; 6 | 7 | describe('chapter06', () => { 8 | describe('110-sets-from-other-set', () => { 9 | it('should define all the objects', () => { 10 | expect(union).to.be.a('set'); 11 | }); 12 | 13 | it('should have the right size', () => { 14 | expect(union.size).to.be.equal(3); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter06/120-use-for-weaksetsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | rootObj, 7 | replacer, 8 | } from '../../src/chapter06/120-use-for-weaksets'; 9 | 10 | describe('chapter06', () => { 11 | describe('120-use-for-weaksets', () => { 12 | it('should define all the objects', () => { 13 | expect(rootObj).to.be.a('object'); 14 | expect(replacer).to.be.a('function'); 15 | }); 16 | 17 | it('should serialize correctly', () => { 18 | const s = JSON.stringify(rootObj, replacer); 19 | expect(s).to.be.ok; 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/chapter06/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter07/010-object-literal-getters-settersSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import song from '../../src/chapter07/010-object-literal-getters-setters'; 6 | 7 | describe('chapter07', () => { 8 | describe('010-object-literal-getters-setters', () => { 9 | it('should define all the objects', () => { 10 | expect(song).to.be.a('object'); 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | expect(song.name).to.be.equal('Yellow Submarine'); 15 | expect(song.duration).to.be.a('number'); 16 | song.name = 'some'; 17 | expect(song.name).to.be.equal('some'); 18 | song.duration = 3.00; 19 | expect(song.duration).to.be.equal(3.00); 20 | expect(song.getName).to.be.a('function'); 21 | }); 22 | 23 | it('duration of the song cannot be less than 0 min', () => { 24 | try { 25 | song.duration = -1; 26 | } catch (e) { 27 | expect(e).not.to.be.undefined; 28 | song.duration = 3.00; 29 | } 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/chapter07/020-object-literal-computed-propertySpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import song from '../../src/chapter07/020-object-literal-computed-property'; 6 | 7 | describe('chapter07', () => { 8 | describe('020-object-literal-computed-property', () => { 9 | it('should define all the objects', () => { 10 | expect(song).to.be.a('object'); 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | expect(song.getName()).to.be.equal(song.name); 15 | expect(song.getAlbum()).to.be.equal(song.album); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter07/025-revealing-module-patternSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import greeter from '../../src/chapter07/025-revealing-module-pattern'; 6 | 7 | describe('chapter07', () => { 8 | describe('025-revealing-module-pattern', () => { 9 | it('should define all the objects', () => { 10 | expect(greeter).to.be.a('object'); 11 | expect(greeter.greet).to.be.a('function'); 12 | expect(greeter.salutation).to.be.a('function'); 13 | }); 14 | 15 | it('should greet the invokee', () => { 16 | expect(greeter.greet('Raju')).to.be.equal('Hola Raju!'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter07/050-object-literal-method-shorthandSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import song from '../../src/chapter07/050-object-literal-method-shorthand'; 6 | 7 | describe('chapter07', () => { 8 | describe('050-object-literal-method-shorthand', () => { 9 | it('should define all the objects', () => { 10 | expect(song).to.be.a('object'); 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | expect(song.name).to.be.equal('All You Need Is Love'); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter07/060-object-literal-inline-computed-propertySpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import song from '../../src/chapter07/060-object-literal-inline-computed-property'; 6 | 7 | describe('chapter07', () => { 8 | describe('060-object-literal-inline-computed-property', () => { 9 | it('should define all the objects', () => { 10 | expect(song).to.be.a('object'); 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | expect(song.getName()).to.be.equal(song.name); 15 | expect(song.getAlbum()).to.be.equal(song.album); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter07/070-revealing-module-pattern-shorthandSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import greeter from '../../src/chapter07/070-revealing-module-pattern-shorthand'; 6 | 7 | describe('chapter07', () => { 8 | describe('070-revealing-module-pattern-shorthand', () => { 9 | it('should define all the objects', () => { 10 | expect(greeter).to.be.a('object'); 11 | expect(greeter.greet).to.be.a('function'); 12 | expect(greeter.salutation).to.be.a('function'); 13 | }); 14 | 15 | it('should greet the invokee', () => { 16 | expect(greeter.greet('Raju')).to.be.equal('Hola Raju!'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter07/080-trailing-comma-arrays-objectsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | friedmanBooks, 7 | hoyteBook, 8 | } from '../../src/chapter07/080-trailing-comma-arrays-objects'; 9 | 10 | describe('chapter07', () => { 11 | describe('080-trailing-comma-arrays-objects', () => { 12 | it('should define all the objects', () => { 13 | expect(friedmanBooks).to.be.a('array'); 14 | expect(hoyteBook).to.be.a('object'); 15 | }); 16 | 17 | it('should correctly initialize the object', () => { 18 | expect(friedmanBooks.length).to.be.equal(3); 19 | expect(hoyteBook.author).to.be.equal('Doug Hoyte'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/chapter07/090-trailing-comma-functionsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import rate from '../../src/chapter07/090-trailing-comma-functions'; 6 | 7 | describe('chapter07', () => { 8 | describe('090-trailing-comma-functions', () => { 9 | it('should define all the objects', () => { 10 | expect(rate).to.be.a('function'); 11 | }); 12 | 13 | it('should correctly initialize the object', () => { 14 | expect(rate('bla', 4)).to.be.equal('You rated \'bla\' 4 stars'); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter07/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter08/020-method-hook-using-stringsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | LOG_LEVEL, 7 | DEBUG, 8 | INFO, 9 | ERROR, 10 | simpleLogger, 11 | loggableObj, 12 | } from '../../src/chapter08/020-method-hook-using-strings'; 13 | 14 | describe('chapter08', () => { 15 | describe('020-method-hook-using-strings', () => { 16 | it('should define all the objects', () => { 17 | expect(LOG_LEVEL).to.be.a('string'); 18 | expect(DEBUG).to.be.a('string'); 19 | expect(INFO).to.be.a('string'); 20 | expect(ERROR).to.be.a('string'); 21 | expect(simpleLogger).to.be.a('function'); 22 | expect(loggableObj).to.be.a('object'); 23 | }); 24 | 25 | it('should define the behavior correctly', () => { 26 | expect(loggableObj[LOG_LEVEL]).to.be.equal(INFO); 27 | 28 | const otherObj = { 29 | [LOG_LEVEL]: ERROR, 30 | }; 31 | 32 | expect(simpleLogger(otherObj, 'some message')).to.be.equal('ERROR: some message'); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/chapter08/040-symbols-are-uniqueSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | symbol1, 7 | symbol2, 8 | symbol3, 9 | } from '../../src/chapter08/040-symbols-are-unique'; 10 | 11 | describe('chapter08', () => { 12 | describe('040-symbols-are-unique', () => { 13 | it('should define all the objects', () => { 14 | expect(symbol1).to.be.a('symbol'); 15 | expect(symbol2).to.be.a('symbol'); 16 | expect(symbol3).to.be.a('symbol'); 17 | }); 18 | 19 | it('should define the behavior correctly', () => { 20 | expect(symbol1 === symbol2).to.be.false; 21 | expect(symbol3 === symbol2).to.be.false; 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/chapter08/050-overriding-object-keys-with-symbolsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | ITERATOR, 7 | iterableObject, 8 | objWithExistingKey, 9 | } from '../../src/chapter08/050-overriding-object-keys-with-symbols'; 10 | 11 | describe('chapter08', () => { 12 | describe('050-overriding-object-keys-with-symbols', () => { 13 | it('should define all the objects', () => { 14 | expect(ITERATOR).to.be.a('symbol'); 15 | expect(iterableObject).to.be.a('object'); 16 | expect(objWithExistingKey).to.be.a('object'); 17 | }); 18 | 19 | it('should define the properties correctly', () => { 20 | expect(iterableObject.name).to.be.equal('iterable'); 21 | expect(iterableObject[ITERATOR]).to.be.a('function'); 22 | 23 | expect(objWithExistingKey[ITERATOR]).to.be.a('function'); 24 | expect(objWithExistingKey[ITERATOR]()).to.be.equal('Works!'); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter08/070-method-hook-using-symbolsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | LOG_LEVEL, 7 | DEBUG, 8 | INFO, 9 | ERROR, 10 | simpleLogger, 11 | loggableObj, 12 | } from '../../src/chapter08/070-method-hook-using-symbols'; 13 | 14 | describe('chapter08', () => { 15 | describe('070-method-hook-using-symbols', () => { 16 | it('should define all the objects', () => { 17 | expect(LOG_LEVEL).to.be.a('symbol'); 18 | expect(DEBUG).to.be.a('string'); 19 | expect(INFO).to.be.a('string'); 20 | expect(ERROR).to.be.a('string'); 21 | expect(simpleLogger).to.be.a('function'); 22 | expect(loggableObj).to.be.a('object'); 23 | }); 24 | 25 | it('should define the behavior correctly', () => { 26 | expect(loggableObj[LOG_LEVEL]).to.be.equal(INFO); 27 | 28 | const otherObj = { 29 | [LOG_LEVEL]: ERROR, 30 | }; 31 | 32 | expect(simpleLogger(otherObj, 'some message')).to.be.equal('ERROR: some message'); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/chapter08/080-switch-case-using-stringsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | LOG_LEVEL, 7 | DEBUG, 8 | INFO, 9 | ERROR, 10 | MY_LEVEL, 11 | simpleLogger, 12 | loggableObj, 13 | } from '../../src/chapter08/080-switch-case-using-strings'; 14 | 15 | describe('chapter08', () => { 16 | describe('080-switch-case-using-strings', () => { 17 | it('should define all the objects', () => { 18 | expect(LOG_LEVEL).to.be.a('symbol'); 19 | expect(DEBUG).to.be.a('string'); 20 | expect(INFO).to.be.a('string'); 21 | expect(ERROR).to.be.a('string'); 22 | expect(simpleLogger).to.be.a('function'); 23 | expect(loggableObj).to.be.a('object'); 24 | }); 25 | 26 | it('should define the behavior correctly', () => { 27 | expect(loggableObj[LOG_LEVEL]).to.be.equal(MY_LEVEL); 28 | 29 | const otherObj = { 30 | [LOG_LEVEL]: ERROR, 31 | }; 32 | 33 | expect(simpleLogger(otherObj, 'some message')).to.be.equal('ERROR: some message'); 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/chapter08/090-switch-case-using-symbolsSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | LOG_LEVEL, 7 | DEBUG, 8 | INFO, 9 | ERROR, 10 | simpleLogger, 11 | loggableObj, 12 | } from '../../src/chapter08/090-switch-case-using-symbols'; 13 | 14 | describe('chapter08', () => { 15 | describe('090-switch-case-using-symbols', () => { 16 | it('should define all the objects', () => { 17 | expect(LOG_LEVEL).to.be.a('symbol'); 18 | expect(DEBUG).to.be.a('symbol'); 19 | expect(INFO).to.be.a('symbol'); 20 | expect(ERROR).to.be.a('symbol'); 21 | expect(simpleLogger).to.be.a('function'); 22 | expect(loggableObj).to.be.a('object'); 23 | }); 24 | 25 | it('should define the behavior correctly', () => { 26 | expect(loggableObj[LOG_LEVEL]).to.be.equal(ERROR); 27 | 28 | const otherObj = { 29 | [LOG_LEVEL]: ERROR, 30 | }; 31 | 32 | expect(simpleLogger(otherObj, 'some message')).to.be.equal('ERROR: some message'); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/chapter08/100-symbol-forSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | global, 7 | otherGlobal, 8 | } from '../../src/chapter08/100-symbol-for'; 9 | 10 | describe('chapter08', () => { 11 | describe('100-symbol-keyFor', () => { 12 | it('should define all the objects', () => { 13 | expect(global).to.be.a('symbol'); 14 | expect(otherGlobal).to.be.a('symbol'); 15 | }); 16 | 17 | it('should define the behavior correctly', () => { 18 | expect(global).to.be.equal(otherGlobal); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter08/110-symbol-keyForSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | global, 7 | key, 8 | } from '../../src/chapter08/110-symbol-keyFor'; 9 | 10 | describe('chapter08', () => { 11 | describe('110-symbol-keyFor', () => { 12 | it('should define all the objects', () => { 13 | expect(global).to.be.a('symbol'); 14 | expect(key).to.be.a('string'); 15 | }); 16 | 17 | it('should define the behavior correctly', () => { 18 | expect(key).to.be.equal(Symbol.keyFor(global)); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter08/120-string-matchSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | url, 7 | split, 8 | } from '../../src/chapter08/120-string-match'; 9 | 10 | describe('chapter08', () => { 11 | describe('120-string-match', () => { 12 | it('should define all the objects', () => { 13 | expect(url).to.be.a('string'); 14 | expect(split).to.be.a('array'); 15 | }); 16 | 17 | it('should define the behavior correctly', () => { 18 | expect(split.length).to.be.equal(1); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter08/130-symbol-matchSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | passwordObfuscator, 7 | credentials, 8 | } from '../../src/chapter08/130-symbol-match'; 9 | 10 | describe('chapter08', () => { 11 | describe('130-symbol-match', () => { 12 | it('should define all the objects', () => { 13 | expect(passwordObfuscator).to.be.a('object'); 14 | expect(credentials).to.be.a('array'); 15 | }); 16 | 17 | it('should define the behavior correctly', () => { 18 | expect(credentials[0]).to.be.equal('admin:***********'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter08/140-object-enumerate-keysSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | obj, 7 | } from '../../src/chapter08/140-object-enumerate-keys'; 8 | 9 | describe('chapter08', () => { 10 | describe('140-object-enumerate-keys', () => { 11 | it('should define all the objects', () => { 12 | expect(obj).to.be.a('object'); 13 | }); 14 | 15 | it('should define the behavior correctly', () => { 16 | expect(Object.keys(obj).length).to.be.equal(1); 17 | expect(Object.getOwnPropertyNames(obj).length).to.be.equal(2); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter08/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter09/010-for-in-loop-arraysSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | arr, 7 | } from '../../src/chapter09/010-for-in-loop-arrays'; 8 | 9 | describe('chapter09', () => { 10 | describe('010-for-in-loop-arrays', () => { 11 | it('should define all the objects', () => { 12 | expect(arr).to.be.a('array'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter09/020-es5-fibonacciSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | fibonacci, 7 | } from '../../src/chapter09/020-es5-fibonacci'; 8 | 9 | describe('chapter09', () => { 10 | describe('020-es5-fibonacci', () => { 11 | it('should define all the objects', () => { 12 | expect(fibonacci).to.be.a('function'); 13 | }); 14 | 15 | it('should define the properties correctly', () => { 16 | expect(fibonacci(0)).to.be.eql([]); 17 | expect(fibonacci(1)).to.be.eql([0]); 18 | expect(fibonacci(2)).to.be.eql([0, 1]); 19 | expect(fibonacci(10)).to.be.eql([0, 1, 1, 2, 3, 5, 8, 13, 21, 34]); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/chapter09/030-simple-iterableSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import arrayList from '../../src/chapter09/030-simple-iterable'; 6 | 7 | describe('chapter09', () => { 8 | describe('030-simple-iterable', () => { 9 | it('should define all the objects', () => { 10 | expect(arrayList).to.be.a('object'); 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | expect(arrayList[Symbol.iterator]).to.be.a('function'); 15 | const iterator = arrayList[Symbol.iterator](); 16 | expect(iterator).to.be.a('object'); 17 | expect(iterator.next()).to.be.eql({ 18 | done: false, 19 | value: 1, 20 | }); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter09/035-for-of-loop-arraySpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import arr from '../../src/chapter09/035-for-of-loop-array'; 6 | 7 | describe('chapter09', () => { 8 | describe('035-for-of-loop-array', () => { 9 | it('should define all the objects', () => { 10 | expect(arr).to.be.a('array'); 11 | }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/chapter09/040-loops-for-of-all-datastructuresSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | array, 7 | set, 8 | map, 9 | string, 10 | } from '../../src/chapter09/040-loops-for-of-all-datastructures'; 11 | 12 | describe('chapter09', () => { 13 | describe('040-loops-for-of-all-datastructures', () => { 14 | it('should define all the objects', () => { 15 | expect(array).to.be.a('array'); 16 | expect(set).to.be.a('set'); 17 | expect(map).to.be.a('map'); 18 | expect(string).to.be.a('string'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter09/045-iterator-returnSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | incrementor, 7 | } from '../../src/chapter09/045-iterator-return'; 8 | 9 | describe('chapter09', () => { 10 | describe('045-iterator-return', () => { 11 | it('should define all the objects', () => { 12 | expect(incrementor).to.be.a('object'); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter09/050-simple-generatorSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | generatorDemo, 7 | } from '../../src/chapter09/050-simple-generator'; 8 | 9 | describe('chapter09', () => { 10 | describe('050-simple-generator', () => { 11 | it('should define all the objects', () => { 12 | expect(generatorDemo()[Symbol.iterator]).not.to.be.undefined; 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter09/060-generator-fibonacciSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | fibonacci, 7 | } from '../../src/chapter09/060-generator-fibonacci'; 8 | 9 | describe('chapter09', () => { 10 | describe('060-generator-fibonacci', () => { 11 | it('should define all the objects', () => { 12 | expect(fibonacci()[Symbol.iterator]).not.to.be.undefined; 13 | }); 14 | 15 | it('should define the properties correctly', () => { 16 | const gen = fibonacci(); 17 | expect(gen.next().value).to.be.equal(0); 18 | expect(gen.next().value).to.be.equal(1); 19 | expect(gen.next().value).to.be.equal(1); 20 | expect(gen.next().value).to.be.equal(2); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter09/070-simple-generator-pushSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | generatorWithPushDemo, 7 | } from '../../src/chapter09/070-simple-generator-push'; 8 | 9 | describe('chapter09', () => { 10 | describe('070-simple-generator-push', () => { 11 | it('should define all the objects', () => { 12 | expect(generatorWithPushDemo()[Symbol.iterator]).not.to.be.undefined; 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter09/080-generator-returnSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | generatorFunctionWithTryCatchFinally, 7 | } from '../../src/chapter09/080-generator-return'; 8 | 9 | describe('chapter09', () => { 10 | describe('080-generator-return', () => { 11 | it('should define all the objects', () => { 12 | expect(generatorFunctionWithTryCatchFinally()[Symbol.iterator]).not.to.be.undefined; 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter09/090-yield -generatorSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | inner, 7 | outer, 8 | } from '../../src/chapter09/090-yield-generator'; 9 | 10 | describe('chapter09', () => { 11 | describe('090-yield*-generator', () => { 12 | it('should define all the objects', () => { 13 | expect(inner()[Symbol.iterator]).not.to.be.undefined; 14 | expect(outer()[Symbol.iterator]).not.to.be.undefined; 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter09/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter10/010-basic-promiseSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import p from '../../src/chapter10/010-basic-promise'; 6 | 7 | describe('chapter10', () => { 8 | describe('010-basic-promise', () => { 9 | it('should define all the objects', () => { 10 | expect(p).not.to.be.undefined; 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | p.then((msg) => { 15 | expect(msg).to.be.equal('I transitioned successfully'); 16 | }); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/chapter10/020-promisify-xhrSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | import mock from 'xhr-mock'; 5 | 6 | import asyncRequest from '../../src/chapter10/020-promisify-xhr'; 7 | 8 | describe('chapter10', () => { 9 | describe('020-promisify-xhr', () => { 10 | 11 | beforeEach(() => mock.setup()); 12 | 13 | // put the real XHR object back and clear the mocks after each test 14 | afterEach(() => mock.teardown()); 15 | 16 | it('should successfully GET', async () => { 17 | // expect.assertions(2); 18 | 19 | mock.get('/', { 20 | headers: { 'Content-Length': '12' }, 21 | body: 'Hello World!', 22 | }); 23 | 24 | const a = await asyncRequest('GET', '/'); 25 | expect(a).to.be.equal('Hello World!'); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/chapter10/025-promisify-xhr-with-then-catchSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | import mock from 'xhr-mock'; 5 | 6 | import asyncRequest from '../../src/chapter10/025-promisify-xhr-with-then-catch'; 7 | 8 | describe('chapter10', () => { 9 | describe('025-promisify-xhr-with-then-catch', () => { 10 | 11 | beforeEach(() => mock.setup()); 12 | 13 | // put the real XHR object back and clear the mocks after each test 14 | afterEach(() => mock.teardown()); 15 | 16 | it('should successfully GET', async () => { 17 | // expect.assertions(2); 18 | 19 | mock.get('/', { 20 | headers: { 'Content-Length': '12' }, 21 | body: 'Hello World!', 22 | }); 23 | 24 | const a = await asyncRequest('GET', '/'); 25 | expect(a).to.be.equal('Hello World!'); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/chapter10/030-promise-allSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | import mock from 'xhr-mock'; 5 | 6 | import asyncRequest from '../../src/chapter10/030-promise-all'; 7 | 8 | 9 | describe('chapter10', () => { 10 | describe('030-promise-all', () => { 11 | 12 | beforeEach(() => mock.setup()); 13 | 14 | // put the real XHR object back and clear the mocks after each test 15 | afterEach(() => mock.teardown()); 16 | 17 | it('should successfully GET', async () => { 18 | // expect.assertions(2); 19 | 20 | mock.get('/', { 21 | headers: { 'Content-Length': '12' }, 22 | body: 'Hello World!', 23 | }); 24 | 25 | const a = await asyncRequest('GET', '/'); 26 | expect(a).to.be.equal('Hello World!'); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/chapter10/040-promise-raceSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | import mock from 'xhr-mock'; 5 | 6 | import asyncRequest from '../../src/chapter10/040-promise-race'; 7 | 8 | 9 | describe('chapter10', () => { 10 | describe('040-promise-race', () => { 11 | 12 | beforeEach(() => mock.setup()); 13 | 14 | // put the real XHR object back and clear the mocks after each test 15 | afterEach(() => mock.teardown()); 16 | 17 | it('should successfully GET', async () => { 18 | // expect.assertions(2); 19 | 20 | mock.get('/', { 21 | headers: { 'Content-Length': '12' }, 22 | body: 'Hello World!', 23 | }); 24 | 25 | const a = await asyncRequest('GET', '/'); 26 | expect(a).to.be.equal('Hello World!'); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/chapter10/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter11/010-basic-classSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | Person, 7 | raju, 8 | venkat, 9 | } from '../../src/chapter11/010-basic-class'; 10 | 11 | describe('chapter11', () => { 12 | describe('010-basic-class', () => { 13 | it('should define all the objects', () => { 14 | expect(Person).not.to.be.undefined; 15 | 16 | expect(raju).not.to.be.undefined; 17 | expect(venkat).not.to.be.undefined; 18 | }); 19 | 20 | it('should define all properties for Person correctly', () => { 21 | expect(raju.getName).not.to.be.undefined; 22 | expect(raju.sayHello).not.to.be.undefined; 23 | expect(raju.age).to.be.undefined; 24 | expect(raju.warCry).to.be.undefined; 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter11/015-basic-prototypal-inheritanceSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax */ 2 | import { 3 | expect, 4 | } from 'chai'; 5 | 6 | import { 7 | SuperHero, 8 | thor, 9 | } from '../../src/chapter11/015-basic-prototypal-inheritance'; 10 | 11 | describe('chapter11', () => { 12 | describe('015-basic-prototypal-inheritance', () => { 13 | it('should define all the objects', () => { 14 | expect(SuperHero).not.to.be.undefined; 15 | 16 | expect(thor).not.to.be.undefined; 17 | }); 18 | 19 | it('should define all properties for SuperHero correctly', () => { 20 | expect(thor.getName).not.to.be.undefined; 21 | expect(thor.sayHello).not.to.be.undefined; 22 | expect(thor.superpower).not.to.be.undefined; 23 | expect(thor.warCry).not.to.be.undefined; 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/chapter11/020-classesSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | Person, 7 | raju, 8 | venkat, 9 | } from '../../src/chapter11/020-classes'; 10 | 11 | describe('chapter11', () => { 12 | describe('020-classes', () => { 13 | it('should define all the objects', () => { 14 | expect(Person).not.to.be.undefined; 15 | 16 | expect(raju).not.to.be.undefined; 17 | expect(venkat).not.to.be.undefined; 18 | }); 19 | 20 | it('should define all properties for Person correctly', () => { 21 | expect(raju.getName).not.to.be.undefined; 22 | expect(raju.sayHello).not.to.be.undefined; 23 | expect(raju.age).to.be.undefined; 24 | expect(raju.warCry).to.be.undefined; 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter11/030-classes-prototypal-inheritanceSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import { 6 | SuperHero, 7 | thor, 8 | } from '../../src/chapter11/030-classes-prototypal-inheritance'; 9 | 10 | describe('chapter11', () => { 11 | describe('030-classes-prototypal-inheritance', () => { 12 | it('should define all the objects', () => { 13 | expect(SuperHero).not.to.be.undefined; 14 | 15 | expect(thor).not.to.be.undefined; 16 | }); 17 | 18 | it('should define all properties for SuperHero correctly', () => { 19 | expect(thor.getName).not.to.be.undefined; 20 | expect(thor.sayHello).not.to.be.undefined; 21 | expect(thor.superpower).not.to.be.undefined; 22 | expect(thor.warCry).not.to.be.undefined; 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/chapter11/040-classes-static-methodsSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-new */ 2 | import { 3 | expect, 4 | } from 'chai'; 5 | 6 | import SuperHero from '../../src/chapter11/040-classes-static-methods'; 7 | 8 | describe('chapter11', () => { 9 | describe('040-classes-static-methods', () => { 10 | it('should define all the objects', () => { 11 | expect(SuperHero).not.to.be.undefined; 12 | }); 13 | 14 | it('should define all properties for SuperHero correctly', () => { 15 | new SuperHero('raju', 'talking'); 16 | new SuperHero('nate', 'slides'); 17 | // we create two inside the file itself 18 | expect(SuperHero.count()).to.be.equal(4); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter11/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter12/010-iefe-for-varSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import counter from '../../src/chapter12/010-iefe-for-var'; 4 | 5 | 6 | describe('chapter12', () => { 7 | describe('010-iefe-for-var', () => { 8 | it('should return a counter', () => { 9 | expect(counter).to.exist; 10 | }); 11 | 12 | it('should have 0 steps', () => { 13 | expect(counter.getCount()).to.equal(1); 14 | }); 15 | 16 | it('should have increment steps', () => { 17 | counter.increment(); 18 | expect(counter.getCount()).to.equal(2); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter12/060-named-importsSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { // <1> 4 | sin, 5 | cos, 6 | tan, 7 | } from '../../src/chapter12/060-named-imports'; 8 | 9 | 10 | describe('chapter12', () => { 11 | describe('060-named-imports', () => { 12 | it('should define all the objects', () => { 13 | expect(sin).not.to.be.undefined; 14 | expect(cos).not.to.be.undefined; 15 | expect(tan).not.to.be.undefined; 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter12/070-named-aliased-importSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { // <1> 4 | sine, 5 | cosine, 6 | trignometry, 7 | } from '../../src/chapter12/090-aliasing-imports'; 8 | 9 | 10 | describe('chapter12', () => { 11 | describe('090-aliasing-imports', () => { 12 | it('should define all the objects', () => { 13 | expect(sine).not.to.be.undefined; 14 | expect(cosine).not.to.be.undefined; 15 | expect(trignometry).not.to.be.undefined; 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter12/080-wildcard-importSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import trigFns from '../../src/chapter12/080-wildcard-import'; // <1> 4 | 5 | 6 | describe('chapter12', () => { 7 | describe('080-wildcard-import', () => { 8 | it('should define all the objects', () => { 9 | expect(trigFns).not.to.be.undefined; 10 | }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/chapter12/090-aliasing-importsSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { // <1> 4 | sine, 5 | cosine, 6 | tan, 7 | trignometry, 8 | } from '../../src/chapter12/070-named-aliased-import'; 9 | 10 | 11 | describe('chapter12', () => { 12 | describe('070-named-aliased-import', () => { 13 | it('should define all the objects', () => { 14 | expect(sine).not.to.be.undefined; 15 | expect(cosine).not.to.be.undefined; 16 | expect(tan).not.to.be.undefined; 17 | expect(trignometry).not.to.be.undefined; 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter12/100-default-importSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { 4 | myTrignometry, 5 | sin, 6 | cos, 7 | tan, 8 | } from '../../src/chapter12/100-default-import'; 9 | 10 | 11 | describe('chapter12', () => { 12 | describe('100-default-import', () => { 13 | it('should define all the objects', () => { 14 | expect(myTrignometry).not.to.be.undefined; 15 | expect(sin).not.to.be.undefined; 16 | expect(cos).not.to.be.undefined; 17 | expect(tan).not.to.be.undefined; 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter12/110-default-with-aliased-importsSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { 4 | myTrignometry, 5 | sine, 6 | cosine, 7 | tan, 8 | } from '../../src/chapter12/110-default-with-aliased-imports'; 9 | 10 | 11 | describe('chapter12', () => { 12 | describe('110-default-with-aliased-imports', () => { 13 | it('should define all the objects', () => { 14 | expect(myTrignometry).not.to.be.undefined; 15 | expect(sine).not.to.be.undefined; 16 | expect(cosine).not.to.be.undefined; 17 | expect(tan).not.to.be.undefined; 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter12/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter13/010-array-prototype-equalsSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import first from '../../src/chapter13/010-array-prototype-equals'; 5 | 6 | describe('chapter13', () => { 7 | after(() => Reflect.deleteProperty(Array.prototype, 'equals')); 8 | 9 | describe('010-array-prototype-equals', () => { 10 | it('should define all the objects', () => { 11 | expect(Array.prototype.equals).not.to.be.undefined; 12 | expect(Array.prototype.equals).to.be.a('function'); 13 | }); 14 | 15 | it('should correctly define all the properties', () => { 16 | expect([1, 2, 3, [4, 5]].equals([1, 2, 3, [4, 5]])).to.be.true; 17 | expect([1, 2, 3, [4, 5]].equals([1, 2, 3])).to.be.false; 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter13/020-intercept-methodSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import intercept from '../../src/chapter13/020-intercept-method'; 4 | 5 | describe('chapter13', () => { 6 | describe('020-intercept-method', () => { 7 | it('should define all the objects', () => { 8 | expect(intercept).not.to.be.undefined; 9 | }); 10 | 11 | it('should correctly define all the properties', () => { 12 | const obj = { 13 | name: 'Raju', 14 | getFirstName() { return this.name; }, 15 | }; 16 | let method; 17 | const checker = (m) => { 18 | method = m; 19 | }; 20 | intercept(obj, checker); 21 | obj.getFirstName(); 22 | expect(method).to.be.equal('getFirstName'); 23 | obj.name = 'Venkat'; 24 | // shouldn't invoke the intercepter 25 | expect(method).to.be.equal('getFirstName'); 26 | expect(obj.name).to.be.equal('Venkat'); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/chapter13/030-simple-proxySpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { 4 | toBeIntercepted, 5 | proxied, 6 | } from '../../src/chapter13/030-simple-proxy'; 7 | 8 | describe('chapter13', () => { 9 | describe('030-simple-proxy', () => { 10 | it('should define all the objects', () => { 11 | expect(toBeIntercepted).not.to.be.undefined; 12 | expect(proxied).not.to.be.undefined; 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/chapter13/060-singleton-using-proxiesSpec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | import { 4 | singletonFactory, 5 | SuperHeroService, 6 | } from '../../src/chapter13/060-singleton-using-proxies'; 7 | 8 | describe('chapter13', () => { 9 | describe('060-singleton-using-proxies', () => { 10 | it('should define all the objects', () => { 11 | expect(singletonFactory).not.to.be.undefined; 12 | expect(singletonFactory).to.be.a('function'); 13 | expect(SuperHeroService).not.to.be.undefined; 14 | expect(SuperHeroService).to.be.a('function'); 15 | }); 16 | 17 | it('should correctly define all the properties', () => { 18 | const SingletonSuperHeroService = singletonFactory(SuperHeroService); 19 | const service1 = new SingletonSuperHeroService(); 20 | const service2 = new SingletonSuperHeroService(); 21 | expect(service1 === service2).to.equal(true); 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/chapter13/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter14/010-simple-math-imperativelySpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import { 5 | firstSyncOp, 6 | secondSyncOp, 7 | thirdSyncOp, 8 | result, 9 | } from '../../src/chapter14/010-simple-math-imperatively'; 10 | 11 | describe('chapter14', () => { 12 | describe('010-simple-math-imperatively', () => { 13 | it('should define all the objects', () => { 14 | expect(firstSyncOp).not.to.be.undefined; 15 | expect(secondSyncOp).not.to.be.undefined; 16 | expect(thirdSyncOp).not.to.be.undefined; 17 | expect(result).not.to.be.undefined; 18 | }); 19 | 20 | it('should correctly define all the properties', () => { 21 | expect(firstSyncOp()).to.be.equal(10); 22 | expect(secondSyncOp(10)).to.be.equal(30); 23 | expect(thirdSyncOp(20)).to.be.equal(50); 24 | expect(result).to.be.equal(60); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter14/020-simple-math-using-promisesSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import { 5 | firstAsyncOp, 6 | secondAsyncOp, 7 | thirdAsyncOp, 8 | result, 9 | } from '../../src/chapter14/020-simple-math-using-promises'; 10 | 11 | describe('chapter14', () => { 12 | describe('020-simple-math-using-promises', () => { 13 | it('should define all the objects', () => { 14 | expect(firstAsyncOp).not.to.be.undefined; 15 | expect(secondAsyncOp).not.to.be.undefined; 16 | expect(thirdAsyncOp).not.to.be.undefined; 17 | expect(result).not.to.be.undefined; 18 | }); 19 | 20 | it('should correctly define all the properties', async () => { 21 | const f = await firstAsyncOp(); 22 | expect(f).to.be.equal(10); 23 | 24 | const s = await secondAsyncOp(10); 25 | expect(s).to.be.equal(30); 26 | 27 | const t = await thirdAsyncOp(10); 28 | expect(t).to.be.equal(40); 29 | 30 | const r = await result; 31 | expect(r).to.be.equal(60); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/chapter14/025-sync-async-conditionalSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import { 5 | syncConditionalResult, 6 | asyncConditionalResult, 7 | } from '../../src/chapter14/025-sync-async-conditional'; 8 | 9 | describe('chapter14', () => { 10 | describe('025-sync-async-conditional', () => { 11 | it('should define all the objects', () => { 12 | expect(syncConditionalResult).not.to.be.undefined; 13 | expect(asyncConditionalResult).not.to.be.undefined; 14 | }); 15 | 16 | it('should correctly define all the properties', () => { 17 | expect(syncConditionalResult).to.be.equal(40); 18 | asyncConditionalResult.then(val => expect(val).to.be.equal(40)); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter14/030-simple-asyncSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import { 5 | implicitPromise, 6 | explicitPromise, 7 | } from '../../src/chapter14/030-simple-async'; 8 | 9 | describe('chapter14', () => { 10 | describe('030-simple-async', () => { 11 | it('should define all the objects', () => { 12 | expect(implicitPromise).not.to.be.undefined; 13 | expect(implicitPromise).to.be.a('function'); 14 | expect(explicitPromise).not.to.be.undefined; 15 | expect(explicitPromise).to.be.a('function'); 16 | }); 17 | 18 | it('should correctly define all the properties', () => { 19 | implicitPromise().then(val => expect(val).to.be.a('array')); 20 | explicitPromise().then(val => expect(val).to.be.a('array')); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/chapter14/040-simple-async-awaitSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import firstAsyncOp from '../../src/chapter14/040-simple-async-await'; 5 | 6 | describe('chapter14', () => { 7 | describe('040-simple-async-await', () => { 8 | it('should define all the objects', () => { 9 | expect(firstAsyncOp).not.to.be.undefined; 10 | expect(firstAsyncOp).to.be.a('function'); 11 | }); 12 | 13 | it('should correctly define all the properties', async () => { 14 | const ret = await firstAsyncOp(); 15 | expect(ret).to.be.equal(10); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/chapter14/050-simple-math-using-async-awaitSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import { 5 | firstAsyncOp, 6 | secondAsyncOp, 7 | thirdAsyncOp, 8 | result, 9 | } from '../../src/chapter14/050-simple-math-using-async-await'; 10 | 11 | describe('chapter14', () => { 12 | describe('050-simple-math-using-async-await', () => { 13 | it('should define all the objects', () => { 14 | expect(firstAsyncOp).not.to.be.undefined; 15 | expect(secondAsyncOp).not.to.be.undefined; 16 | expect(thirdAsyncOp).not.to.be.undefined; 17 | expect(result).not.to.be.undefined; 18 | }); 19 | 20 | it('should correctly define all the properties', () => { 21 | firstAsyncOp().then(val => expect(val).to.be.equal(10)); 22 | secondAsyncOp(10).then(val => expect(val).to.be.equal(30)); 23 | thirdAsyncOp(10).then(val => expect(val).to.be.equal(40)); 24 | result.then(val => expect(val).to.be.equal(60)); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/chapter14/055-sync-async-conditional-againSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import result from '../../src/chapter14/055-sync-async-conditional-again'; 5 | 6 | describe('chapter14', () => { 7 | describe('055-sync-async-conditional-again', () => { 8 | it('should define all the objects', () => { 9 | expect(result).not.to.be.undefined; 10 | }); 11 | 12 | it('should correctly define all the properties', async () => { 13 | const r = await result; 14 | expect(r).to.be.equal(40); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/chapter14/060-fetch-with-async-awaitSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { expect } from 'chai'; 3 | 4 | import { 5 | getWithPromises, 6 | getWithAsyncAwait, 7 | } from '../../src/chapter14/060-fetch-with-async-await'; 8 | 9 | describe('chapter14', () => { 10 | describe('060-fetch-with-async-await', () => { 11 | it('should define all the objects', () => { 12 | expect(getWithPromises).not.to.be.undefined; 13 | expect(getWithAsyncAwait).not.to.be.undefined; 14 | }); 15 | 16 | it('should correctly define all the properties', () => { 17 | const url = 'https://my-json-server.typicode.com/typicode/demo/posts'; 18 | 19 | getWithPromises(url) 20 | .then((json) => { 21 | expect(json).to.be.a('array'); 22 | }); 23 | 24 | getWithAsyncAwait(url) 25 | .then((json) => { 26 | expect(json).to.be.a('array'); 27 | }); 28 | }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/chapter14/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/chapter15/010-asynchronous-iterationSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import promiseList from '../../src/chapter15/010-asynchronous-iteration'; 6 | 7 | describe('chapter15', () => { 8 | describe('010-asynchronous-iteration', () => { 9 | it('should define all the objects', () => { 10 | expect(promiseList).to.be.a('array'); 11 | }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/chapter15/020-asynchronous-generator-async-awaitSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import promiseList from '../../src/chapter15/020-asynchronous-generator-async-await'; 6 | 7 | describe('chapter15', () => { 8 | describe('020-asynchronous-generator-async-await', () => { 9 | it('should define all the objects', () => { 10 | expect(promiseList).to.be.a('array'); 11 | }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/chapter15/030-simple-sync-generatorSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import asyncGenerator from '../../src/chapter15/030-simple-sync-generator'; 6 | 7 | describe('chapter15', () => { 8 | describe('030-simple-sync-generator', () => { 9 | it('should define all the objects', () => { 10 | expect(asyncGenerator()[Symbol.iterator]).not.to.be.undefined; 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | const gen = asyncGenerator(); 15 | expect(gen.next().value).to.be.a('promise'); 16 | expect(gen.next().value).to.be.a('promise'); 17 | expect(gen.next().value).to.be.undefined; 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter15/050-simple-async-iterable-for-async-awaitSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import result from '../../src/chapter15/050-simple-async-iterable-for-async-await'; 6 | 7 | describe('chapter15', () => { 8 | describe('050-simple-async-iterable-for-async-await', () => { 9 | it('should define all the objects', () => { 10 | expect(result).to.be.a('promise'); 11 | }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/chapter15/070-simple-async-iterable-try-catchSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import SimpleRejectingIterable from '../../src/chapter15/070-simple-async-iterable-try-catch'; 6 | 7 | describe('chapter15', () => { 8 | describe('070-simple-async-iterable-try-catch', () => { 9 | it('should define all the objects', () => { 10 | expect(SimpleRejectingIterable).to.be.a('function'); 11 | }); 12 | 13 | it('should define the properties correctly', () => { 14 | expect(new SimpleRejectingIterable()[Symbol.asyncIterator]).to.be.a('function'); 15 | 16 | const iterator = new SimpleRejectingIterable()[Symbol.asyncIterator](); 17 | expect(iterator).to.be.a('object'); 18 | 19 | iterator.next().catch(e => expect(e).not.to.be.undefined); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/chapter15/080-for-await-of-sync-iterableSpec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax */ 2 | import { 3 | expect, 4 | } from 'chai'; 5 | 6 | import promiseList from '../../src/chapter15/080-for-await-of-sync-iterable'; 7 | 8 | describe('chapter15', () => { 9 | describe('080-for-await-of-sync-iterable', () => { 10 | it('should define all the objects', () => { 11 | expect(promiseList).to.be.a('array'); 12 | }); 13 | 14 | it('should define the properties correctly', async () => { 15 | for await (const p of promiseList) { 16 | expect(p).to.be.a('string'); 17 | } 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/chapter15/090-aync-generatorSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | expect, 3 | } from 'chai'; 4 | 5 | import asyncGenerator from '../../src/chapter15/090-aync-generator'; 6 | 7 | describe('chapter15', () => { 8 | describe('090-aync-generator', () => { 9 | it('should define all the objects', () => { 10 | expect(asyncGenerator()[Symbol.asyncIterator]).not.to.be.undefined; 11 | expect(asyncGenerator()[Symbol.asyncIterator]).to.be.a('function'); 12 | }); 13 | 14 | it('should define the properties correctly', async () => { 15 | const gen = asyncGenerator(); 16 | expect((await gen.next()).value).to.be.equal('My value is 10 at index: 1'); 17 | expect((await gen.next()).value).to.be.equal('My value is 20 at index: 2'); 18 | expect((await gen.next()).done).to.be.equal(true); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/chapter15/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --recursive 2 | --reporter spec 3 | --ui bdd 4 | -------------------------------------------------------------------------------- /tools/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-extraneous-dependencies": [ 4 | "error", 5 | { 6 | "optionalDependencies": false, 7 | "peerDependencies": false 8 | } 9 | ], 10 | "strict": "off" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tools/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | ConfirmFileOp=0 3 | IconResource=C:\Program Files\Google\Drive File Stream\29.1.85.2056\GoogleDriveFS.exe,20 4 | --------------------------------------------------------------------------------