├── .gitignore ├── ES6.png ├── LICENSE ├── README.md ├── session-1 ├── .babelrc ├── README.md ├── dist │ └── bundle.js ├── index.html ├── package.json ├── src │ ├── 00_scope.js │ ├── 01_context.js │ ├── 02_scope.js │ ├── 03_const.js │ └── index.js └── webpack.config.js ├── session-2 ├── .babelrc ├── 00_template_string.js ├── 01_multiple_lines.js ├── 02_tagging.js ├── 03_raw.js ├── 03_tagging.js ├── 04_i18n.js ├── 05_destrucuring_arrays.js ├── 06_destructuring_objects.js ├── 07_default_values.js ├── 08_spread.js ├── 09_arrow.js ├── 10_arrow_this.js ├── README.md ├── dev.webpack.config.js ├── package.json └── src │ └── index.js ├── session-3 ├── .babelrc ├── 00_constructor.js ├── 00_context.js ├── 00_prototype.js ├── 01_es5_classes.js ├── 02_es5_subclasses.js ├── 03_es5_clone.js ├── 04_es6_classes.js ├── 05_es6_subclasses.js ├── 06_object_literals.js ├── 07_iterators.js ├── 08_generators.js ├── README.md └── package.json ├── session-4 ├── .babelrc ├── 00_string_methods.js ├── 01_Number_Math.js ├── 02_array.js ├── 03_sets.js ├── 04_maps.js ├── 05_weak_sets.js ├── 06_weak_maps.js ├── 07_animation_es5.js ├── 08_animation_promise.js ├── 09_animation_parallel.js ├── 10_promise.js ├── README.md ├── modules │ ├── aliases.js │ ├── app.js │ ├── mathematics.js │ ├── persona.js │ ├── suma.js │ └── vars.js └── package.json ├── session-5 ├── .babelrc ├── 00_symbols.js ├── 01_proxies.js ├── 02_reflection.js ├── 03_decorators.js ├── README.md └── package.json └── session-6 ├── .babelrc ├── README.md ├── dist ├── main.css └── main.js ├── package.json ├── src ├── components │ ├── card │ │ ├── _index.scss │ │ └── index.js │ └── html │ │ ├── div.js │ │ ├── htmlComponent.js │ │ ├── image.js │ │ ├── index.js │ │ └── text.js ├── domain │ ├── entity.js │ ├── factories │ │ └── pokemon.js │ ├── index.js │ ├── pokemon │ │ ├── apiPokemonRepository.js │ │ ├── pokemonEntity.js │ │ ├── pokemonListUseCase.js │ │ ├── pokemonRepository.js │ │ └── spriteEntity.js │ └── useCase.js ├── index.js └── index.scss └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /ES6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EscuelaIt/Curso-ECMAScript-6/2ae84040cf35d01c45dd74b44e966a43277484fe/ES6.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Curso Javascript ECMAScript 6 2 | Repositorio del [Curso ECMAScript 6](http://escuela.it/cursos/javascript-ecmascript-6/) 3 | 4 | ## Slides 5 | [Aprende ECMAScript 2015](https://slides.com/danieldelacruzcalvo/aprende-ecmascript-2015) 6 | 7 | ## Recursos de aprendizaje 8 | * [ES6: New Features & Comparison](http://es6-features.org/) 9 | * [ECMAScript 2015 (ES6) in Node.JS](https://nodejs.org/en/docs/es6/) 10 | * [Learn ES2015 with Babel](https://babeljs.io/docs/learn-es2015/) 11 | * [Tabla de compatibilidad de ECMAScript 2015](https://kangax.github.io/compat-table/es6/) 12 | * [Lista de Recursos para aprender ECMAScript 2015](https://github.com/ericdouglas/ES6-Learning) 13 | 14 | ![](https://github.com/EscuelaIt/Curso-ECMAScript-6/blob/master/ES6.png) 15 | -------------------------------------------------------------------------------- /session-1/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | presets: [ 'es2015' ], 3 | plugins: [] 4 | } -------------------------------------------------------------------------------- /session-1/README.md: -------------------------------------------------------------------------------- 1 | # Sesión 1 2 | 3 | ### Enlaces 4 | 5 | * [Babel](https://babeljs.io) 6 | * [ECMAScript 2015 (ES6) in Node.js](https://nodejs.org/en/docs/es6/) 7 | * [Immutable.js](https://facebook.github.io/immutable-js/) 8 | * [Material Theme](https://equinusocio.github.io/material-theme/) 9 | 10 | ### Recursos 11 | Para que podamos utilizar los packages instalados en un proyecto sin tener que definir la ruta `./node_modules/.bin/` en cada uno de ellos, podemos insertar en nuestro fichero `.bashrc`, `.bash_profile`, etc... la siguiente línea para añadir al `PATH` la ruta de los binarios. 12 | 13 | ``` 14 | export PATH=$PATH:./node_modules/.bin 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /session-1/dist/bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) 10 | /******/ return installedModules[moduleId].exports; 11 | 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ exports: {}, 15 | /******/ id: moduleId, 16 | /******/ loaded: false 17 | /******/ }; 18 | 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | 22 | /******/ // Flag the module as loaded 23 | /******/ module.loaded = true; 24 | 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | 29 | 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | 36 | /******/ // __webpack_public_path__ 37 | /******/ __webpack_require__.p = ""; 38 | 39 | /******/ // Load entry module and return exports 40 | /******/ return __webpack_require__(0); 41 | /******/ }) 42 | /************************************************************************/ 43 | /******/ ([ 44 | /* 0 */ 45 | /***/ function(module, exports) { 46 | 47 | "use strict"; 48 | 49 | var suma = function suma(a, b) { 50 | return a + b; 51 | }; 52 | debugger; 53 | console.log(suma(2, 3)); 54 | 55 | /***/ } 56 | /******/ ]); -------------------------------------------------------------------------------- /session-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /session-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "session-1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "babel": "babel src --out-dir dist", 8 | "dist": "webpack", 9 | "start": "babel-node" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-cli": "^6.5.1", 16 | "babel-loader": "^6.2.3", 17 | "babel-preset-es2015": "^6.5.0", 18 | "webpack": "^1.12.14" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /session-1/src/00_scope.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var x; 3 | console.log(x); 4 | if(true){ 5 | x = 'hola mundo'; 6 | } 7 | console.log(x); 8 | })(); 9 | 10 | -------------------------------------------------------------------------------- /session-1/src/01_context.js: -------------------------------------------------------------------------------- 1 | // var obj = { 2 | // foo: function() { 3 | // console.log(this === obj); 4 | // } 5 | // }; 6 | 7 | // obj.foo(); 8 | 9 | function bar(){ 10 | console.log(this); 11 | } 12 | 13 | new bar(); -------------------------------------------------------------------------------- /session-1/src/02_scope.js: -------------------------------------------------------------------------------- 1 | var a = 'I am global'; 2 | 3 | function foo(){ 4 | let b = 'I am local'; 5 | console.log('Existe a en el alcance local?', !!a); 6 | console.log('Existe b en el alcance local?', !!b); 7 | 8 | if(true){ 9 | let c = 'Soy una variable de la condición if'; 10 | } 11 | 12 | let c = 3; 13 | 14 | console.log('cuanto vale c?', c); 15 | 16 | // console.log('Existe c fuera del if?', !!c); 17 | 18 | for(let d = 0; d < 10; d++){ 19 | // ... 20 | } 21 | 22 | // console.log('Existe d fuera del for?', !!d); 23 | } 24 | 25 | foo(); 26 | // console.log('Existe a en el alcance global?', !!a); 27 | // console.log('Existe b en el alcance global?', !!b); -------------------------------------------------------------------------------- /session-1/src/03_const.js: -------------------------------------------------------------------------------- 1 | const USER = { 2 | name: 'Daniel', 3 | surname: 'de la Cruz', 4 | age: 32 5 | }; 6 | 7 | USER.name = 'Joan'; 8 | USER.age = 'cuarenta'; 9 | USER.kk = 3; 10 | 11 | delete USER.age; 12 | 13 | console.log(USER); 14 | const LIGHT = '#AAA'; 15 | 16 | const colors: { 17 | background: LIGHT 18 | } -------------------------------------------------------------------------------- /session-1/src/index.js: -------------------------------------------------------------------------------- 1 | const suma = (a, b) => a + b; 2 | debugger; 3 | console.log(suma(2, 3)); -------------------------------------------------------------------------------- /session-1/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | const config = { 5 | entry: path.join(__dirname, '/src'), 6 | output: { 7 | path: './dist', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | test: /\.js?$/, 13 | loaders: [ 'babel' ], 14 | exclude: /node_modules/ 15 | }] 16 | }, 17 | new webpack.optimize.UglifyJsPlugin({ 18 | compress: { 19 | warnings: false 20 | } 21 | }) 22 | } 23 | 24 | module.exports = config; -------------------------------------------------------------------------------- /session-2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015" ], 3 | "plugins": [] 4 | } -------------------------------------------------------------------------------- /session-2/00_template_string.js: -------------------------------------------------------------------------------- 1 | const hello = 'Hello'; 2 | const world = "World"; 3 | 4 | const helloWorld = `${hello}, ${world}!`; 5 | 6 | console.log(helloWorld); 7 | -------------------------------------------------------------------------------- /session-2/01_multiple_lines.js: -------------------------------------------------------------------------------- 1 | const lorem = `Lorem ipsum dolor sit amet, 2 | consectetur adipisicing elit, 3 | sed do eiusmod tempor incididunt 4 | ut labore et dolore magna aliqua. 5 | Ut enim ad minim veniam, 6 | quis nostrud exercitation ullamco 7 | laboris nisi ut aliquip ex ea commodo consequat. 8 | Duis aute irure dolor in reprehenderit in 9 | voluptate velit esse cillum dolore eu fugiat 10 | nulla pariatur. Excepteur sint occaecat cupidatat 11 | non proident, sunt in culpa qui officia deserunt 12 | mollit anim id est laborum. `; 13 | 14 | console.log(lorem); 15 | -------------------------------------------------------------------------------- /session-2/02_tagging.js: -------------------------------------------------------------------------------- 1 | // Sin spread operator 2 | function tag(strings, arg1, arg2){ 3 | console.log(strings) 4 | console.log(arg1) 5 | console.log(arg2) 6 | console.log(arguments) 7 | } 8 | 9 | const pepito = 'Pepito'; 10 | const jose = 'Jose'; 11 | 12 | console.log(tag`Hola, don ${pepito}, hola don ${jose}`); 13 | 14 | // Con spread operator 15 | function newTag(strings, ...args) { 16 | console.log(strings) 17 | console.log(args) 18 | } 19 | 20 | console.log(newTag`Hola, don ${pepito}, hola don ${jose}`); -------------------------------------------------------------------------------- /session-2/03_raw.js: -------------------------------------------------------------------------------- 1 | const raw = function(strings, args) { 2 | return strings.raw[0]; 3 | } 4 | console.log(raw`Hello!\n`); 5 | console.log('next line'); 6 | console.log(`Hello!\n`); 7 | console.log('next line'); -------------------------------------------------------------------------------- /session-2/03_tagging.js: -------------------------------------------------------------------------------- 1 | const tag = function(strings, args) { 2 | return strings.map(function(s){ 3 | return s.split('').map(function(s){ 4 | return `${s}.`; 5 | }) 6 | .join('') 7 | }) 8 | .join(''); 9 | } 10 | 11 | console.log(tag`Hello, World!`); -------------------------------------------------------------------------------- /session-2/04_i18n.js: -------------------------------------------------------------------------------- 1 | const dictionary = { 2 | es: { 3 | 'days ago': 'hace %{count} días' 4 | }, 5 | en: { 6 | 'days ago': '%{count} days ago' 7 | } 8 | }; 9 | 10 | const i18n = function(strings, args) { 11 | const key = strings.join('').trim(); 12 | return dictionary[culture][key].replace('%{count}', args); 13 | }; 14 | 15 | let culture = 'es'; 16 | console.log(i18n`${8} days ago`); 17 | 18 | culture = 'en'; 19 | console.log(i18n`${8} days ago`); 20 | -------------------------------------------------------------------------------- /session-2/05_destrucuring_arrays.js: -------------------------------------------------------------------------------- 1 | const numbers = ['1', '2', '3']; 2 | 3 | // without destructuring 4 | const one = numbers[0]; 5 | const two = numbers[1]; 6 | const three = numbers[2]; 7 | 8 | // with destructuring 9 | const [uno, dos, tres] = numbers; 10 | 11 | console.log(one, two, three); 12 | console.log(uno, dos, tres); 13 | 14 | // also, without assignment: 15 | let ichi, ni, san; 16 | [ichi, ni, san] = ['uno', 'dos', 'tres']; 17 | 18 | console.log(ichi, ni, san); 19 | 20 | // destructuring assignment returning values from a function 21 | function users(){ 22 | return ['joan', 'carlos', 'david', 'dani']; 23 | } 24 | 25 | let [joan, carlos, david, dani] = users(); 26 | console.log(joan, carlos, david, dani); 27 | -------------------------------------------------------------------------------- /session-2/06_destructuring_objects.js: -------------------------------------------------------------------------------- 1 | // object destructuring works exactly the same way as in arrays 2 | let object = { one: 1, two: 2 }; 3 | let {one, two} = object; 4 | console.log(one, two); // 1 2 5 | 6 | // We can destructure values when passing arguments to a function 7 | function suma({a, b} = {}) { 8 | return a + b; 9 | }; 10 | 11 | // now, we can pass separate values 12 | const three = 3; 13 | const four = 4; 14 | console.log(suma({a: three, b: four})); 15 | 16 | // If the properties have the same name than the declared in the function definition, ES6 assigns them automatically 17 | const a = 3; 18 | const b = 4; 19 | console.log(suma({a, b})); 20 | 21 | // or, an object to get its properties destructured 22 | const numbers = { 23 | a: 5, 24 | b: 6 25 | }; 26 | console.log(suma(numbers)); 27 | 28 | // we can alias our destructured variables: 29 | const persona = { nombre: 'Daniel', apellidos: 'de la Cruz' }; 30 | const { nombre: name, apellidos: surname } = persona; 31 | console.log(name); 32 | console.log(surname); 33 | -------------------------------------------------------------------------------- /session-2/07_default_values.js: -------------------------------------------------------------------------------- 1 | // ES5 2 | function drawCircle(options){ 3 | options = options === undefined ? {} : options; 4 | var radius = options.radius === undefined ? 30 : options.radius; 5 | var coords = options.coords === undefined ? { x: 0, y: 0 } : options.coords; 6 | 7 | console.log(radius, coords); 8 | // finally, draw the circle 9 | } 10 | 11 | // ES6 12 | function drawCircle({radius = 30, coords = { x: 0, y: 0}} = {}) { 13 | console.log(radius, coords); 14 | // draw the circle 15 | }; 16 | 17 | drawCircle(); // radius: 30, coords.x: 0, coords.y: 0 } 18 | drawCircle({radius: 10}); // radius: 10, coords.x: 0, coords.y: 0 } 19 | drawCircle({coords: {y: 10, x: 30}, radius: 10}); // radius: 10, coords.x: 30, coords.y: 10 } 20 | 21 | function sayHello({ 22 | name = 'Joan', 23 | surname = 'Leon' 24 | } = {}) { 25 | console.log('Hello', name, surname); 26 | }; 27 | 28 | sayHello(); -------------------------------------------------------------------------------- /session-2/08_spread.js: -------------------------------------------------------------------------------- 1 | // El operador de propagación spread operator permite que una 2 | // expresión sea expandida en situaciones donde se esperan múltiples 3 | // argumentos (llamadas a funciones) o múltiples elementos 4 | // (arrays). 5 | 6 | const values = [1, 2, 3, 4]; 7 | 8 | console.log(values); // returns an array 9 | console.log(...values); // spreads the array and returns the values 10 | 11 | // We can define a spread parameter 12 | function f(args) { 13 | return args.length; 14 | } 15 | 16 | console.log('Without spreading', f(1, 2, 3)); 17 | 18 | function fspread(...args) { 19 | return args.length; 20 | } 21 | 22 | console.log('With spreading', fspread(1, 2, 3)); 23 | 24 | // We can also spread on passing the arguments 25 | function suma(x, y, z) { 26 | return x + y + z; 27 | } 28 | 29 | console.log(suma(...[1, 2, 3])); // 6 30 | 31 | // Spread object properties 32 | const worker = { 33 | id: 1337, 34 | name: 'John', 35 | surname: 'Woo', 36 | age: 35, 37 | job: 'UI designer' 38 | }; 39 | 40 | const customize = function(worker){ 41 | return { 42 | ...worker, 43 | fullName: `Mr./Mrs. ${worker.surname}, ${worker.name}`, 44 | age: `${worker.age} years old` 45 | }; 46 | }; 47 | 48 | console.log(customize(worker)); 49 | -------------------------------------------------------------------------------- /session-2/09_arrow.js: -------------------------------------------------------------------------------- 1 | const echo = text => text; 2 | console.log(echo('Hello, arrow functions!')); 3 | 4 | // with arguments 5 | const suma = (a, b, c) => a + b + c; 6 | console.log(suma(1, 2, 3)); 7 | 8 | // or without 9 | const greet = () => 'Hi again!'; 10 | console.log(greet()); 11 | 12 | // other es6 function improvements are also valid here 13 | const concat = (...args) => args.join(', '); 14 | console.log(concat('one', 'two', 'three', 'four')); 15 | 16 | // For complex operations, we can give the arrow function a body 17 | const resize = ({x, y}, ratio) => { 18 | return { 19 | x: x * ratio, 20 | y: y * ratio 21 | }; 22 | }; 23 | 24 | console.log(resize({x: 5, y: 15}, 100)); 25 | -------------------------------------------------------------------------------- /session-2/10_arrow_this.js: -------------------------------------------------------------------------------- 1 | const randomWinner = function(drivers) { 2 | const winner = Math.floor(Math.random() * (0 - drivers.length) + drivers.length); 3 | return drivers[winner]; 4 | }; 5 | 6 | const F1Race = { 7 | drivers: [ 8 | 'Alonso', 9 | 'Vettel', 10 | 'Button', 11 | 'Massa' 12 | ], 13 | 14 | init: function() { 15 | console.log('Los siguientes pilotos van a comenzar la carrera:', this.drivers); 16 | setTimeout((function() { 17 | console.log('El ganador es', randomWinner(this.drivers)); 18 | }), 1000); 19 | // }).bind(this), 1000); 20 | } 21 | }; 22 | 23 | F1Race.init(); 24 | 25 | //// If we redefine the init function including an arrow: 26 | 27 | // F1Race.init = function() { 28 | // console.log('Los siguientes pilotos van a comenzar la carrera:', this.drivers); 29 | // setTimeout(() => console.log('El ganador es', randomWinner(this.drivers)), 1000); 30 | // }; 31 | // 32 | // F1Race.init(); 33 | -------------------------------------------------------------------------------- /session-2/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /session-2/dev.webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | var APP_PATH = path.join(__dirname, '/src'); 5 | 6 | module.exports = { 7 | context: APP_PATH, 8 | entry: './index.js', 9 | output: { 10 | path: path.join(__dirname, 'dist'), 11 | filename: '[name].js', 12 | publicPath: 'http://localhost:3000/dist' 13 | }, 14 | devServer: { 15 | port: 3000, 16 | stats: { colors: true }, 17 | inline: true, 18 | publicPath: '/dist/' 19 | }, 20 | devtool: 'source-map', 21 | module: { 22 | loaders: [{ 23 | test: /\.js$/, 24 | loaders: [ 'babel' ], 25 | exclude: /node_modules/ 26 | }] 27 | }, 28 | plugins: [ 29 | new webpack.HotModuleReplacementPlugin() 30 | ] 31 | }; -------------------------------------------------------------------------------- /session-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "session-2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "babel-node", 8 | "dev": "webpack-dev-server --config dev.webpack.config.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-cli": "^6.5.1", 15 | "babel-loader": "^6.2.3", 16 | "babel-preset-es2015": "^6.5.0", 17 | "webpack": "^1.12.14", 18 | "webpack-dev-server": "^1.14.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /session-2/src/index.js: -------------------------------------------------------------------------------- 1 | const h1 = function(text) { 2 | const h1 = document.createElement('h1'); 3 | h1.appendChild(document.createTextNode(text)); 4 | return h1; 5 | }; 6 | 7 | document.body.appendChild(h1('Hola alumnos de Escuela IT')); -------------------------------------------------------------------------------- /session-3/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "stage-2" ], 3 | "plugins": [] 4 | } -------------------------------------------------------------------------------- /session-3/00_constructor.js: -------------------------------------------------------------------------------- 1 | // cualquier función utilizada como un constructor se convierte en un constructor :) 2 | var Vehicle = function Vehicle() { 3 | console.log('Sólo soy una función!'); 4 | } 5 | 6 | var motorcycle = new Vehicle(); 7 | 8 | console.log(typeof Vehicle); // function 9 | console.log(typeof Vehicle()); // undefined 10 | console.log(typeof new Vehicle()); // object 11 | 12 | // NOTA: No es aconsejable retornar ningún valor en funciones constructoras, 13 | // ya que el valor retornado sobreescribirá la instancia del objeto creado 14 | 15 | // motorcycle tiene una propiedad constructor que es la función Vehicle 16 | console.log(motorcycle.constructor === Vehicle); 17 | 18 | // motorcycle es UNA INSTANCIA de Vehicle 19 | console.log(motorcycle instanceof Vehicle); 20 | 21 | // la propiedad constructor no aparece si enumeramos las propiedades de motorcycle 22 | console.log(motorcycle); 23 | 24 | // Pero podemos crearla y sobreescribirla 25 | var Postman = function Postman() {}; 26 | motorcycle.constructor = Postman; 27 | 28 | console.log(motorcycle); 29 | 30 | // Pero, sigue siendo una instancia de Vehicle? 31 | console.log(motorcycle.constructor === Postman); 32 | console.log(motorcycle instanceof Postman); 33 | console.log(motorcycle instanceof Vehicle); -------------------------------------------------------------------------------- /session-3/00_context.js: -------------------------------------------------------------------------------- 1 | var Person = function Person(name) { 2 | this.name = name; 3 | } 4 | 5 | var myself = new Person('Dani'); 6 | 7 | // name solo existe dentro del contexto del objeto 'myself' 8 | console.log(typeof name); // undefined 9 | console.log(myself.name); // Dani 10 | 11 | // Si utilizamos Person como una función no constructora: 12 | Person('Joan'); 13 | console.log(name); -------------------------------------------------------------------------------- /session-3/00_prototype.js: -------------------------------------------------------------------------------- 1 | var Vehicle = function Vehicle() { 2 | console.log('Sólo soy una función!'); 3 | } 4 | 5 | Vehicle.prototype.wheelCount = 4; 6 | 7 | var truck = new Vehicle(); 8 | console.log(truck.wheelCount); // 4 9 | 10 | // 11 | Vehicle.prototype.wheelCount = 6; 12 | console.log(truck.wheelCount); 13 | 14 | // modificar wheelCount en la instancia no modifica 15 | // el prototype de la función constructora 16 | truck.wheelCount = 8; 17 | console.log(Vehicle.prototype.wheelCount); 18 | console.log(truck.wheelCount); 19 | 20 | // wheelCount ya no está delegado 21 | Vehicle.prototype.wheelCount = 10; 22 | console.log(truck.wheelCount); 23 | 24 | // obviamente siempre podemos hacer lo mismo con métodos, ya que 25 | // un método no es más que una función asignada a una propiedad: 26 | Vehicle.prototype.go = function go() { return 'Brooommmm!' }; 27 | console.log(truck.go()); -------------------------------------------------------------------------------- /session-3/01_es5_classes.js: -------------------------------------------------------------------------------- 1 | var Vehicle = function Vehicle(color, model) { 2 | // Initialization 3 | this.color = color; 4 | this.model = model; 5 | } 6 | 7 | // Instance methods 8 | Vehicle.prototype = { 9 | go: function go() { 10 | return "Brrooooom!"; 11 | }, 12 | whoami: function whoami() { 13 | return "I am a " + this.color + " " + this.model; 14 | } 15 | } 16 | 17 | var motorcycle = new Vehicle('yellow', 'Vespa'); 18 | 19 | console.log(motorcycle.whoami()); 20 | console.log(motorcycle.go()); 21 | -------------------------------------------------------------------------------- /session-3/02_es5_subclasses.js: -------------------------------------------------------------------------------- 1 | var Vehicle = function Vehicle(color, model) { 2 | // Initialization 3 | this.color = color; 4 | this.model = model; 5 | } 6 | 7 | // Instance methods 8 | Vehicle.prototype = { 9 | go: function go() { 10 | return "Brrooooom!"; 11 | }, 12 | whoami: function whoami() { 13 | return "I am a " + this.color + " " + this.model; 14 | } 15 | } 16 | 17 | var Car = function Car() {}; 18 | Car.prototype = new Vehicle('red', 'Ford'); 19 | Car.prototype.honk = function honk() { return "MOOOOC!" }; 20 | var car = new Car(); 21 | console.log(car.honk()); // MOOOOC! 22 | console.log(car.go()); // Brrooooom! 23 | console.log(car.color); // red 24 | console.log(car instanceof Car); // true 25 | console.log(car instanceof Vehicle); // true -------------------------------------------------------------------------------- /session-3/03_es5_clone.js: -------------------------------------------------------------------------------- 1 | function clone(parent){ 2 | var Clone = function() {}; 3 | Clone.prototype = parent; 4 | return new Clone(); 5 | } 6 | 7 | var car = { color: 'white' }; 8 | var ibiza = clone(car); 9 | var leon = clone(car); 10 | var toledo = clone(car); 11 | toledo.color = 'blue'; 12 | 13 | console.log(ibiza.color); // white 14 | console.log(leon.color); // white 15 | console.log(toledo.color); // blue 16 | 17 | car.color = 'black'; 18 | 19 | console.log(ibiza.color); // black 20 | console.log(leon.color); // black 21 | console.log(toledo.color); // blue -------------------------------------------------------------------------------- /session-3/04_es6_classes.js: -------------------------------------------------------------------------------- 1 | class Point { 2 | constructor(x, y) { 3 | this.x = x; 4 | this.y = y; 5 | } 6 | toString() { 7 | return `(${this.x}, ${this.y})`; 8 | } 9 | } 10 | 11 | var p = new Point(25, 8); 12 | console.log(p.toString()); //(25, 8) 13 | 14 | 15 | // la clase no es más que una función!! 16 | console.log(typeof Point); // function 17 | 18 | // pero no puede ser utilizada directamente, solo con new 19 | // Point(); 20 | // > TypeError: Classes can't be function-called 21 | 22 | class Sample{ 23 | constructor(value){ 24 | this.value = value; 25 | } 26 | static staticMethod(){ 27 | return 'Puedes llamar al método estático sin instanciar la clase'; 28 | } 29 | prototypeMethod(){ 30 | return 'Solo puedes llamar al método de prototipo mediante una instancia de la clase'; 31 | } 32 | } 33 | 34 | const sample = new Sample(123); 35 | console.log(sample); 36 | console.log(Sample.staticMethod()); 37 | //console.log(Sample.prototypeMethod()); // TypeError: Sample.prototipo is not a function 38 | console.log(sample.prototypeMethod()); 39 | //console.log(sample.staticMethod()); // TypeError: sample.staticMethod is not a function -------------------------------------------------------------------------------- /session-3/05_es6_subclasses.js: -------------------------------------------------------------------------------- 1 | class Point { 2 | constructor(x, y) { 3 | this.x = x; 4 | this.y = y; 5 | } 6 | toString() { 7 | return `(${this.x}, ${this.y})`; 8 | } 9 | } 10 | 11 | // La clase padre asigna las coordenadas mediante super() 12 | // La subclase sobreescribe el toString() 13 | class ColorPoint extends Point { 14 | constructor(x, y, color) { 15 | super(x, y); 16 | this.color = color; 17 | } 18 | toString() { 19 | return `Punto dibujado en coordenadas ${super.toString()} de color ${this.color}`; 20 | } 21 | } 22 | 23 | const cp = new ColorPoint(25, 8, 'verde'); 24 | console.log(cp.toString()); // (25, 8) de color verde 25 | console.log(cp instanceof ColorPoint) // true 26 | console.log(cp instanceof Point) // true -------------------------------------------------------------------------------- /session-3/06_object_literals.js: -------------------------------------------------------------------------------- 1 | // un object literal es una lista de pares de clave-valor 2 | // rodeados por corchetes 3 | var myObject = { 4 | name: 'Daniel', 5 | age: 32, 6 | married: true 7 | } 8 | 9 | // pueden ser de cualquier tipo 10 | var mySuperCoolObject = { 11 | images: ["one.gif", "two.gif", "three.gif", "four.gif"], 12 | location: { 13 | x: 40.8374, 14 | y: 300.1771 15 | }, 16 | move: function(x, y) { 17 | this.location.x += x; 18 | this.location.y += y; 19 | } 20 | }; 21 | 22 | const myES6Object = { 23 | foo(){ 24 | // ... 25 | }, 26 | bar(x, y){ 27 | // ... 28 | } 29 | } 30 | 31 | const propertyKey = 'foo'; 32 | const ar = 'ar'; 33 | const object = { 34 | [propertyKey]: true, 35 | [`b${ar}`]: 123 36 | }; 37 | 38 | console.log(object) 39 | 40 | const methodKey = 'greeting'; 41 | const yetAnotherObject = { 42 | [methodKey]() { 43 | return 'Hello!'; 44 | } 45 | }; 46 | 47 | console.log(yetAnotherObject.greeting()) -------------------------------------------------------------------------------- /session-3/07_iterators.js: -------------------------------------------------------------------------------- 1 | // for of crea un bucle que itera sobre objetos iterables. 2 | 3 | var numbers = [1, 2, 3, 4]; 4 | 5 | for(const number of numbers){ 6 | console.log(number); 7 | } 8 | 9 | // Creamos objeto iterable con una función next(); 10 | // Llamar a .next() nos dará un objeto coneniendo el valor, 11 | // o indicándonos que no hay más valores 12 | const numberIterator = numbers[Symbol.iterator](); 13 | console.log(numberIterator.next()) 14 | 15 | // Hagamos un objeto que itere sobre las palabras de un string: 16 | class LoremIpsum { 17 | constructor(text) { 18 | this._text = text; 19 | } 20 | 21 | [Symbol.iterator]() { 22 | const re = /\S+/g; 23 | const text = this._text; 24 | return { 25 | next() { 26 | const match = re.exec(text); 27 | if(match) { 28 | return { value: match[0], done: false }; 29 | } 30 | return { value: undefined, done: true }; 31 | } 32 | } 33 | } 34 | } 35 | 36 | const lorem = new LoremIpsum('Lorem ipsum dolor sit amet, consectetur adipisicing elit. Unde voluptatem eveniet ipsum in similique maxime sunt eaque veritatis sapiente. Fuga minus, non cumque deleniti consequatur. Odit reprehenderit non fugit cum!'); 37 | 38 | for (let word of lorem){ 39 | console.log(word) 40 | } 41 | 42 | // Bonus: crea un array mediante spread a partir de un iterable 43 | console.log([...lorem]) 44 | console.log(...lorem); -------------------------------------------------------------------------------- /session-3/08_generators.js: -------------------------------------------------------------------------------- 1 | // Los generadores son funciones que pueden ser 2 | // pausadas y resumidas 3 | function* generatorFunction() { 4 | console.log('First'); 5 | yield; 6 | console.log('Second'); 7 | } 8 | 9 | // cuando llamamos a la función generador, no ejecuta 10 | // el cuerpo de la función, sino que devuelve un objeto generador: 11 | const generatorObject = generatorFunction(); 12 | 13 | // El generador implementa una interfaz que le proporciona 14 | // un método next(), que ejecutará el cuerpo de la función 15 | // hasta encontrar un yield. En este punto, se detendrá. 16 | // 17 | // La función además devuelve un objeto de tipo: 18 | // { 19 | // value: el valor retornado por yield 20 | // done: indica si ha finalizado la ejecución del cuerpo de la función 21 | // } 22 | console.log(generatorObject.next()); 23 | 24 | // Si volvemos a llamar, done valdrá true porque ya ha finalizado 25 | // la ejecución del cuerpo de la función 26 | console.log(generatorObject.next()); 27 | 28 | // A partir de este punto, siempre valdrá true 29 | console.log(generatorObject.next()); 30 | 31 | // Los generadores, al implementar .next(), son iterables 32 | function* abc() { 33 | yield 'a'; 34 | yield 'b'; 35 | yield 'c'; 36 | } 37 | 38 | for (const char of abc()) { 39 | console.log(char); 40 | } 41 | 42 | const alphabet = [...abc()]; 43 | console.log(alphabet); 44 | 45 | const [a, b, c] = abc(); 46 | console.log(a); 47 | console.log(b); 48 | console.log(c); 49 | 50 | // Los generadores suelen ser una forma más sencilla de describir un iterador. 51 | // Volviendo al ejemplo de antes: 52 | class LoremIpsum { 53 | constructor(text) { 54 | this._text = text; 55 | } 56 | 57 | *words() { 58 | const re = /\S+/g; 59 | let match; 60 | while(match = re.exec(this._text)){ 61 | yield match[0]; 62 | } 63 | } 64 | } 65 | 66 | const lorem = new LoremIpsum('Lorem ipsum dolor sit amet, consectetur adipisicing elit. Unde voluptatem eveniet ipsum in similique maxime sunt eaque veritatis sapiente. Fuga minus, non cumque deleniti consequatur. Odit reprehenderit non fugit cum!'); 67 | 68 | for (let word of lorem.words()){ 69 | console.log(word) 70 | } 71 | 72 | class Users { 73 | constructor(people) { 74 | this._people = people; 75 | } 76 | 77 | *alias() { 78 | for (let person of this._people) { 79 | yield person.sex === 'M' ? `Mr. ${person.name}` 80 | : `Mrs. ${person.name}`; 81 | } 82 | } 83 | } 84 | 85 | const people = new Users([ 86 | {sex: 'M', name: 'John' }, 87 | { sex: 'W', name: 'Lucia' } 88 | ]); 89 | 90 | for (let person of people.alias()){ 91 | console.log(person) 92 | } 93 | -------------------------------------------------------------------------------- /session-3/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /session-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "session-3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "babel-node" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-cli": "^6.4.5", 13 | "babel-preset-es2015": "^6.3.13", 14 | "babel-preset-stage-2": "^6.3.13" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /session-4/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "stage-2" ], 3 | "plugins": [] 4 | } -------------------------------------------------------------------------------- /session-4/00_string_methods.js: -------------------------------------------------------------------------------- 1 | const lorem = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non, sint distinctio in perferendis temporibus quod, vitae, explicabo exercitationem labore deserunt repellat doloremque molestias tempora, consectetur facere cum obcaecati nihil libero!'; 2 | 3 | console.log(lorem.startsWith('Lorem')); 4 | console.log(lorem.endsWith('libero!')); 5 | console.log(lorem.includes('dolor')); 6 | 7 | console.log(lorem.startsWith('ipsum', 6)); 8 | 9 | console.log('x'.repeat(3)); -------------------------------------------------------------------------------- /session-4/01_Number_Math.js: -------------------------------------------------------------------------------- 1 | console.log(Number.isInteger(25)); // true 2 | console.log(Number.isInteger(25.0)); // true 3 | console.log(Number.isInteger(25.1)); // false 4 | 5 | console.log(Number.isNaN(NaN)) // false -------------------------------------------------------------------------------- /session-4/02_array.js: -------------------------------------------------------------------------------- 1 | // El método Array.of() crea una nueva instancia Array 2 | // con un número variable de elementos pasados como argumento, 3 | // independientemente del número o del tipo. 4 | 5 | // La diferencia entre Array.of() y el constructor Array reside 6 | // en como maneja los parámetros de tipo entero: Array.of(42) 7 | // crea un array con un solo elemento, 42, mientras Array(42) 8 | // crea un array con 42 elementos, el cual, cada uno es de tipo undefined. 9 | 10 | let items = new Array(1, 2); // length is 2 11 | console.log(items.length); // 2 12 | console.log(items[0]); // 1 13 | console.log(items[1]); // 2 14 | 15 | items = new Array(2); 16 | console.log(items.length); // 2 17 | console.log(items[0]); // undefined 18 | console.log(items[1]); // undefined 19 | 20 | items = Array.of(2); 21 | console.log(items.length); // 1 22 | console.log(items[0]); // 2 23 | 24 | 25 | function doSomething(){ 26 | console.log(arguments); 27 | console.log(typeof arguments); 28 | // arguments "parece un array, pero no lo es. Lo siguiente da error" 29 | // console.log(arguments.map(a => a)); 30 | 31 | // Podemos convertirlo en un array con Array.from 32 | let args = Array.from(arguments); 33 | console.log(args.map(a => a)); 34 | } 35 | 36 | doSomething(1, 2, 3); 37 | 38 | 39 | 40 | let numbers = [25, 30, 35, 40, 45]; 41 | 42 | console.log(numbers.find(n => n > 33)); // 35 43 | console.log(numbers.findIndex(n => n > 33)); // 2 44 | 45 | 46 | 47 | let numbers = [1, 2, 3, 4]; 48 | numbers.fill(1, 2); 49 | console.log(numbers.toString()); // 1,2,1,1 50 | numbers.fill(0, 1, 3); 51 | console.log(numbers.toString()); // 1,0,0,1 -------------------------------------------------------------------------------- /session-4/03_sets.js: -------------------------------------------------------------------------------- 1 | // Un set es una lista de valores que no puede contener 2 | // duplicados. 3 | let es5Set = {}; 4 | es5Set.foo = true; 5 | 6 | // checking for existence 7 | if (es5Set.foo) { 8 | console.log('do something') 9 | } 10 | 11 | // Un set en ES6 se define de la forma siguiente: 12 | let set = new Set(); 13 | set.add('foo'); 14 | console.log(set.has('foo')); 15 | 16 | console.log(set.entries()); 17 | 18 | set.forEach(v => console.log(v)) 19 | for (let item of set) console.log(item); 20 | 21 | var myArray = ["value1", "value2", "value3"]; 22 | 23 | // Use the regular Set constructor to transform an Array into a Set 24 | var mySet = new Set(myArray); 25 | 26 | console.log(mySet.has("value1")); // returns true 27 | 28 | // Use the spread operator to transform a set into an Array. 29 | console.log([...mySet]); // Will show you exactly the same Array as myArray -------------------------------------------------------------------------------- /session-4/04_maps.js: -------------------------------------------------------------------------------- 1 | let course = new Map(); 2 | course.set('title', 'Aprende ECMAScript 2015'); 3 | course.set('sessions', 6); 4 | 5 | console.log([...course]) 6 | 7 | console.log(course.get('title')); 8 | console.log(course.get('sessions')); 9 | 10 | let map = new Map(), 11 | key1 = {}, 12 | key2 = {}; 13 | 14 | map.set(key1, 5); 15 | map.set(key2, 42); 16 | 17 | console.log(map.get(key1)); 18 | console.log(map.get(key2)); -------------------------------------------------------------------------------- /session-4/05_weak_sets.js: -------------------------------------------------------------------------------- 1 | // Los Sets podemos considerarlos Strong Sets, 2 | // ya que conservan la referencia a sus claves 3 | // aunque el objeto original sea eliminado 4 | let set = new Set(), 5 | key = {}; 6 | 7 | set.add(key); 8 | console.log(set.size); // 1 9 | 10 | // eliminate original reference 11 | key = null; 12 | 13 | console.log(set.size); // 1 14 | 15 | // get the original reference back 16 | key = [...set][0]; 17 | 18 | // Esto puede causar un memory leak, por ejemplo si 19 | // nuestro código se ejecuta en una página web que 20 | // mantiene un registro de elementos del DOM que 21 | // podrían ser eliminados por otro script 22 | 23 | // Un weak set es un tipo de set que solo almacena una 24 | // referencia "débil" al objeto 25 | let weakSet = new WeakSet(); 26 | let weakKey = {}; 27 | 28 | // add the object to the set 29 | weakSet.add(weakKey); 30 | 31 | console.log(weakSet.has(weakKey)); // true 32 | 33 | weakSet.delete(weakKey); 34 | 35 | console.log(weakSet.has(weakKey)); // false 36 | -------------------------------------------------------------------------------- /session-4/06_weak_maps.js: -------------------------------------------------------------------------------- 1 | let map = new WeakMap(); 2 | let element = {}; 3 | 4 | map.set(element, "Original"); 5 | 6 | let value = map.get(element); 7 | console.log(value); // "Original" 8 | 9 | // remove the element 10 | element = null; 11 | 12 | // the weak map is empty at this point 13 | console.log(map.get(element)); -------------------------------------------------------------------------------- /session-4/07_animation_es5.js: -------------------------------------------------------------------------------- 1 | 2 | /** ES5 example **/ 3 | function runAnimation(position){ 4 | console.log('Moving to position...', position); 5 | }; 6 | 7 | runAnimation(0); 8 | setTimeout(function() { 9 | runAnimation(1); 10 | setTimeout(function() { 11 | runAnimation(2); 12 | }, 1000); 13 | }, 1000); 14 | -------------------------------------------------------------------------------- /session-4/08_animation_promise.js: -------------------------------------------------------------------------------- 1 | 2 | /** ES6 Promises example **/ 3 | function runAnimation(position){ 4 | console.log('Moving to position...', position); 5 | }; 6 | 7 | function delay(interval){ 8 | return new Promise(function(resolve) { 9 | setTimeout(resolve, interval); 10 | }); 11 | }; 12 | 13 | runAnimation(0); 14 | delay(1000) 15 | .then(function() { 16 | runAnimation(1); 17 | return delay(1000); 18 | }) 19 | .then(function() { 20 | runAnimation(2); 21 | }); 22 | -------------------------------------------------------------------------------- /session-4/09_animation_parallel.js: -------------------------------------------------------------------------------- 1 | function getRandomTimeout() { 2 | return Math.floor(Math.random() * (1 - 5) + 5) * 1000; 3 | }; 4 | 5 | function animation(position){ 6 | console.log('Moving to position', position); 7 | return new Promise(function(resolve) { 8 | setTimeout(resolve, getRandomTimeout()); 9 | }); 10 | }; 11 | 12 | Promise.all([ 13 | animation(1), 14 | animation(2), 15 | animation(3), 16 | animation(4), 17 | animation(5), 18 | animation(6), 19 | animation(7), 20 | animation(8) 21 | ]).then(function() { 22 | animation(9); 23 | }); 24 | -------------------------------------------------------------------------------- /session-4/10_promise.js: -------------------------------------------------------------------------------- 1 | const doPromise = () => { 2 | return new Promise((resolve, reject) => { 3 | // Do something 4 | if(error){ 5 | reject(error); 6 | } 7 | // If succeeds 8 | resolve(result); 9 | }); 10 | }; 11 | 12 | let promiseResult = doPromise(); 13 | 14 | promise.then((result) => { 15 | // fullfillment 16 | }).catch((err) => { 17 | // rejection 18 | }); -------------------------------------------------------------------------------- /session-4/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /session-4/modules/aliases.js: -------------------------------------------------------------------------------- 1 | function greet(text) { 2 | return text; 3 | } 4 | 5 | export { greet as saluda }; -------------------------------------------------------------------------------- /session-4/modules/app.js: -------------------------------------------------------------------------------- 1 | // import suma from './suma'; 2 | 3 | // console.log(suma) 4 | // console.log(suma(2, 2)); 5 | 6 | // // Cuando no usamos default (comentar 7 | // // el import anterior de suma) 8 | // import {suma, resta} from './suma'; 9 | // console.log(suma); 10 | // console.log(resta); 11 | 12 | // // También podemos importarlo todo, y veremos 13 | // // la estructura del módulo 14 | import * as mathematics from './suma'; 15 | console.log(mathematics.default); 16 | 17 | // // import variables 18 | // import {color, name, MAGIC_NUMBER} from './vars' 19 | // console.log(color, name, MAGIC_NUMBER) 20 | 21 | // // import an exported function as default 22 | // import multiplica from './mathematics' 23 | // console.log(multiplica(3, 2)) 24 | 25 | // // import an aliased function 26 | // import {saluda} from './aliases' 27 | // console.log(saluda('hola')) 28 | // console.log(saluda) 29 | 30 | 31 | // // Si tiene una función como default, podemos: 32 | // import mathematics from './suma'; 33 | // console.log(mathematics) 34 | // console.log(mathematics(2, 3)) 35 | 36 | // import Persona from './persona' 37 | // var dani = new Persona('dani', 'de la Cruz') 38 | // console.log(dani) -------------------------------------------------------------------------------- /session-4/modules/mathematics.js: -------------------------------------------------------------------------------- 1 | // define a function 2 | function multiplica(a, b) { 3 | return a * b; 4 | } 5 | 6 | // export later 7 | // export as default, when the module 8 | // itself represents the function 9 | export default multiplica; -------------------------------------------------------------------------------- /session-4/modules/persona.js: -------------------------------------------------------------------------------- 1 | class Persona { 2 | constructor(name, surname){ 3 | this._name = name; 4 | this._surname = surname; 5 | } 6 | }; 7 | 8 | export default Persona; -------------------------------------------------------------------------------- /session-4/modules/suma.js: -------------------------------------------------------------------------------- 1 | // export as default, when the module 2 | // itself represents the function 3 | // export default function(a, b) { 4 | // return a + b; 5 | // } 6 | 7 | // equivalent to previous example 8 | // function suma(a, b) { 9 | // return a + b; 10 | // } 11 | 12 | // export { suma as default }; 13 | 14 | // // When we don't use default, the module 15 | // // is exported as an object that contains 16 | // // the exported function, as it may contain 17 | // // others 18 | export function suma(a, b) { 19 | return a + b; 20 | } 21 | 22 | // // Podemos exportar más de una función 23 | export function resta(a, b) { 24 | return a - b; 25 | } 26 | 27 | // o, exportar una de ellas como default: 28 | export default function multiplicacion(a, b){ 29 | return a * b; 30 | } -------------------------------------------------------------------------------- /session-4/modules/vars.js: -------------------------------------------------------------------------------- 1 | export var color = 'red'; 2 | export let name = 'Daniel'; 3 | export const MAGIC_NUMBER = 7; 4 | 5 | // this will cause a syntax error, since 6 | // export may only appear at the top level 7 | if(true) { 8 | export var error = 'this is a syntax error' 9 | } -------------------------------------------------------------------------------- /session-4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "session-4", 3 | "version": "1.0.0", 4 | "description": "## Módulos ### Organización del código en módulos ### Exportación y tipos #### default, etc #### Exportación como singleton ### Importación ### Alias ## New Math, Number, String, Object APIs ### Novedades en apis ## Estructuras de datos: Map, Set, WeakMap, WeakSet ### TODO ## Promises ### Sintaxis ### Ejemplos", 5 | "main": "00_string_methods.js", 6 | "scripts": { 7 | "start": "babel-node" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-cli": "^6.4.5", 14 | "babel-preset-es2015": "^6.3.13", 15 | "babel-preset-stage-2": "^6.3.13" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /session-5/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "stage-1" ], 3 | "plugins": [ 'transform-decorators-legacy' ] 4 | } 5 | -------------------------------------------------------------------------------- /session-5/00_symbols.js: -------------------------------------------------------------------------------- 1 | // Un símbolo es un tipo de datos cuyos valores son únicos e inmutables 2 | var COLOR_RED = 'Red'; 3 | var COLOR_ORANGE = 'Orange'; 4 | var COLOR_YELLOW = 'Yellow'; 5 | var COLOR_GREEN = 'Green'; 6 | var COLOR_BLUE = 'Blue'; 7 | var COLOR_VIOLET = 'Violet'; 8 | var SKY_BLUE = 'Blue'; 9 | 10 | function printColor(color){ 11 | switch (color) { 12 | case COLOR_RED: 13 | console.log('Rojo'); 14 | break; 15 | case COLOR_ORANGE: 16 | console.log('Naranja'); 17 | break; 18 | case COLOR_YELLOW: 19 | console.log('Amarillo'); 20 | break; 21 | case COLOR_GREEN: 22 | console.log('Verde'); 23 | break; 24 | case COLOR_BLUE: 25 | console.log('Azul'); 26 | break; 27 | case COLOR_VIOLET: 28 | console.log('Violeta'); 29 | break; 30 | case SKY_BLUE: 31 | console.log('Azul cielo'); 32 | break; 33 | default: 34 | throw new Exception('Unknown color: ' + color); 35 | } 36 | } 37 | printColor(COLOR_BLUE); 38 | printColor(SKY_BLUE); 39 | 40 | // Si lo convertimos a 41 | var COLOR_RED = Symbol(); 42 | var COLOR_ORANGE = Symbol(); 43 | var COLOR_YELLOW = Symbol(); 44 | var COLOR_GREEN = Symbol(); 45 | var COLOR_BLUE = Symbol(); 46 | var COLOR_VIOLET = Symbol(); 47 | var SKY_BLUE = Symbol(); 48 | 49 | printColor(COLOR_BLUE); 50 | printColor(SKY_BLUE); 51 | 52 | 53 | console.log(Symbol('foo')); 54 | console.log(Symbol('foo').toString()); 55 | 56 | // Los símbolos usados como claves de objeto no entrarán 57 | // en conflicto con otras claves 58 | var myObj = {}; 59 | var fooSym = Symbol('foo'); 60 | var otherSym = Symbol('bar'); 61 | myObj['foo'] = 'bar'; 62 | myObj[fooSym] = 'baz'; 63 | myObj[otherSym] = 'bing'; 64 | console.log(myObj.foo === 'bar'); 65 | console.log(myObj[fooSym] === 'baz'); 66 | console.log(myObj[otherSym] === 'bing'); 67 | 68 | // Lo podemos utilizar como propiedades de una clase 69 | const _counter = Symbol(); 70 | 71 | class Visits { 72 | constructor({counter = 0} = {}){ 73 | this[_counter] = counter; 74 | } 75 | 76 | add(){ 77 | let counter = this[_counter]; 78 | counter ++; 79 | this[_counter] = counter; 80 | return this[_counter]; 81 | } 82 | } 83 | 84 | let visits = new Visits(); 85 | console.log(visits.add()); 86 | 87 | // No aparecen enumerados como propiedades del objeto 88 | var fooSym = Symbol('foo'); 89 | var myObj = {}; 90 | myObj['foo'] = 'bar'; 91 | myObj[fooSym] = 'baz'; 92 | console.log(Object.keys(myObj)); // -> [ 'foo' ] 93 | console.log(Object.getOwnPropertyNames(myObj)); // -> [ 'foo' ] 94 | console.log(Object.getOwnPropertySymbols(myObj)); // -> [ Symbol(foo) ] 95 | console.log((Object.getOwnPropertySymbols(myObj)[0] === fooSym)); -------------------------------------------------------------------------------- /session-5/01_proxies.js: -------------------------------------------------------------------------------- 1 | require('harmony-reflect') 2 | 3 | /* 4 | Supported in node with: 5 | https://github.com/tvcutsem/harmony-reflect 6 | use node --harmony-proxies 7 | */ 8 | const target = {}; 9 | const handler = { 10 | get(target, propKey, receiver) { 11 | console.log(`get ${propKey}`); 12 | return 'hello'; 13 | } 14 | } 15 | 16 | const proxy = new Proxy(target, handler); 17 | 18 | console.log(proxy.foo); 19 | // get foo 20 | // hello -------------------------------------------------------------------------------- /session-5/02_reflection.js: -------------------------------------------------------------------------------- 1 | 2 | // Reflect.has 3 | var myObject = { 4 | foo: 1 5 | }; 6 | 7 | console.log('foo' in myObject); 8 | console.log(Reflect.has(myObject, 'foo')); -------------------------------------------------------------------------------- /session-5/03_decorators.js: -------------------------------------------------------------------------------- 1 | const readonly = (target, name, descriptor) => { 2 | descriptor.writable = false; 3 | return descriptor; 4 | }; 5 | 6 | class Person { 7 | constructor({first, last}){ 8 | this.first = first; 9 | this.last = last; 10 | } 11 | 12 | @readonly 13 | name() { return `${this.first} ${this.last}` } 14 | } 15 | 16 | const person = new Person({ 17 | first: 'Dani', 18 | last: 'de la Cruz' 19 | }); 20 | 21 | console.log(person.name()); 22 | person.name = () => { return `${this.first}` } -------------------------------------------------------------------------------- /session-5/README.md: -------------------------------------------------------------------------------- 1 | # Sesión 5: Conceptos avanzados 2 | -------------------------------------------------------------------------------- /session-5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "session-5", 3 | "version": "1.0.0", 4 | "description": "## Symbols ### Sintaxis ### Uso ## Proxies ## Reflection ### Explicar concepto de Reflection ### Por qué usar Reflect #### Valores de retorno más útiles #### Sintaxis menos verbosa #### Aplicación de funciones más fiable #### Constructores con un número arbitrario de argumentos ## Decoradores", 5 | "main": "00_symbols.js", 6 | "scripts": { 7 | "start": "babel-node" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-cli": "^6.4.5", 14 | "babel-plugin-transform-decorators-legacy": "^1.3.4", 15 | "babel-preset-es2015": "^6.3.13", 16 | "babel-preset-stage-1": "^6.3.13", 17 | "harmony-reflect": "^1.4.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /session-6/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015" ], 3 | "plugins": [] 4 | } -------------------------------------------------------------------------------- /session-6/README.md: -------------------------------------------------------------------------------- 1 | # Ejercicio práctico 2 | El objetivo del ejercicio consiste en mostrar una lista de recursos atacando a una API, en este caso la [API de Pokémon](http://pokeapi.co/) (aunque se puede escoger cualquier otra). Lo interesante del ejercicio es que nos hemos autoimpuesto la condición de **no utilizar nada de html** y tampoco **ninguna librería ni framework JS para crear componentes de UI**. Absolutamente todo el código debe estar escrito en JavaScript, cumpliendo el estándar ECMAScript 2015. 3 | 4 | ## Entorno de desarrollo 5 | Tanto para trabajar en local como para crear los assets de archivos estáticos para producción, vamos a utilizar [Webpack](https://webpack.github.io/). Puedes encontrar la configuración utilizada en el archivo `webpack.config.js`, con una configuración base en el objeto `common` y dos configuraciones que se combinan en función de la tarea de `npm` utilizada. 6 | 7 | En el caso del `packaje.json`, tenemos cuatro tareas: 8 | * `npm start`: Arranca webpack en modo desarrollo. Para ver tu página, accede a [http://localhost:3000/dist/main](http://localhost:3000/dist/main) 9 | * `npm run build`: Compila el código para distribuirlo en producción 10 | * `npm run clean`: Limpia la carpeta `dist`, en la que se generan los archivos en modo producción 11 | * `npm run fenix`: Limpia la carpeta `node_modules` y realiza una instalación limpia de todas las dependencias npm 12 | -------------------------------------------------------------------------------- /session-6/dist/main.css: -------------------------------------------------------------------------------- 1 | .Card{margin:8px;position:relative;border-radius:2px;overflow:hidden;background-color:#fafafa;height:180px;width:130px;transition:box-shadow .25s;box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12)}.Card-content{padding:20px;border-radius:0 0 2px 2px}.Card-content p{margin:0;padding:0}.Card-title{line-height:10px;font-size:18px;font-weight:300}.Card-image{display:block;border-radius:2px 2px 0 0;position:relative;left:0;right:0;top:0;bottom:0;height:130px;width:100%}html{line-height:1.5;font-family:Roboto,sans-serif;font-weight:400;font-size:15px}body{display:flex;flex-flow:row wrap}a{text-decoration:none} -------------------------------------------------------------------------------- /session-6/dist/main.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="http://localhost:3000/dist",t(0)}([function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}var o=n(1),i=r(o),u=n(7),a=r(u);n(21),a["default"].get("pokemon_list_use_case").execute().then(function(e){return e.map(function(e){return new i["default"](e)})}).then(function(e){var t=!0,n=!1,r=void 0;try{for(var o,i=e[Symbol.iterator]();!(t=(o=i.next()).done);t=!0){var u=o.value;document.body.appendChild(u.render())}}catch(a){n=!0,r=a}finally{try{!t&&i["return"]&&i["return"]()}finally{if(n)throw r}}})},function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;ni;++i)n=o[i],t=n.split("="),r[decodeURIComponent(t[0])]=decodeURIComponent(t[1]);return r}function c(e){var t,n,r,o,i=e.split(/\r?\n/),u={};i.pop();for(var a=0,s=i.length;s>a;++a)n=i[a],t=n.indexOf(":"),r=n.slice(0,t).toLowerCase(),o=w(n.slice(t+1)),u[r]=o;return u}function l(e){return/[\/+]json\b/.test(e)}function f(e){return e.split(/ *; */).shift()}function p(e){return _(e.split(/ *; */),function(e,t){var n=t.split(/ *= */),r=n.shift(),o=n.shift();return r&&o&&(e[r]=o),e},{})}function h(e,t){t=t||{},this.req=e,this.xhr=this.req.xhr,this.text="HEAD"!=this.req.method&&(""===this.xhr.responseType||"text"===this.xhr.responseType)||"undefined"==typeof this.xhr.responseType?this.xhr.responseText:null,this.statusText=this.req.xhr.statusText,this.setStatusProperties(this.xhr.status),this.header=this.headers=c(this.xhr.getAllResponseHeaders()),this.header["content-type"]=this.xhr.getResponseHeader("content-type"),this.setHeaderProperties(this.header),this.body="HEAD"!=this.req.method?this.parseBody(this.text?this.text:this.xhr.response):null}function d(e,t){var n=this;v.call(this),this._query=this._query||[],this.method=e,this.url=t,this.header={},this._header={},this.on("end",function(){var e=null,t=null;try{t=new h(n)}catch(r){return e=new Error("Parser is unable to parse the response"),e.parse=!0,e.original=r,e.rawResponse=n.xhr&&n.xhr.responseText?n.xhr.responseText:null,n.callback(e)}if(n.emit("response",t),e)return n.callback(e,t);if(t.status>=200&&t.status<300)return n.callback(e,t);var o=new Error(t.statusText||"Unsuccessful HTTP response");o.original=e,o.response=t,o.status=t.status,n.callback(o,t)})}function y(e,t){return"function"==typeof t?new d("GET",e).end(t):1==arguments.length?new d("GET",e):new d(e,t)}function m(e,t){var n=y("DELETE",e);return t&&n.end(t),n}var b,v=n(19),_=n(20);b="undefined"!=typeof window?window:"undefined"!=typeof self?self:this,y.getXHR=function(){if(!(!b.XMLHttpRequest||b.location&&"file:"==b.location.protocol&&b.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(e){}return!1};var w="".trim?function(e){return e.trim()}:function(e){return e.replace(/(^\s*|\s*$)/g,"")};y.serializeObject=u,y.parseString=s,y.types={html:"text/html",json:"application/json",xml:"application/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},y.serialize={"application/x-www-form-urlencoded":u,"application/json":JSON.stringify},y.parse={"application/x-www-form-urlencoded":s,"application/json":JSON.parse},h.prototype.get=function(e){return this.header[e.toLowerCase()]},h.prototype.setHeaderProperties=function(e){var t=this.header["content-type"]||"";this.type=f(t);var n=p(t);for(var r in n)this[r]=n[r]},h.prototype.parseBody=function(e){var t=y.parse[this.type];return t&&e&&(e.length||e instanceof Object)?t(e):null},h.prototype.setStatusProperties=function(e){1223===e&&(e=204);var t=e/100|0;this.status=this.statusCode=e,this.statusType=t,this.info=1==t,this.ok=2==t,this.clientError=4==t,this.serverError=5==t,this.error=4==t||5==t?this.toError():!1,this.accepted=202==e,this.noContent=204==e,this.badRequest=400==e,this.unauthorized=401==e,this.notAcceptable=406==e,this.notFound=404==e,this.forbidden=403==e},h.prototype.toError=function(){var e=this.req,t=e.method,n=e.url,r="cannot "+t+" "+n+" ("+this.status+")",o=new Error(r);return o.status=this.status,o.method=t,o.url=n,o},y.Response=h,v(d.prototype),d.prototype.use=function(e){return e(this),this},d.prototype.timeout=function(e){return this._timeout=e,this},d.prototype.clearTimeout=function(){return this._timeout=0,clearTimeout(this._timer),this},d.prototype.abort=function(){return this.aborted?void 0:(this.aborted=!0,this.xhr.abort(),this.clearTimeout(),this.emit("abort"),this)},d.prototype.set=function(e,t){if(i(e)){for(var n in e)this.set(n,e[n]);return this}return this._header[e.toLowerCase()]=t,this.header[e]=t,this},d.prototype.unset=function(e){return delete this._header[e.toLowerCase()],delete this.header[e],this},d.prototype.getHeader=function(e){return this._header[e.toLowerCase()]},d.prototype.type=function(e){return this.set("Content-Type",y.types[e]||e),this},d.prototype.parse=function(e){return this._parser=e,this},d.prototype.accept=function(e){return this.set("Accept",y.types[e]||e),this},d.prototype.auth=function(e,t){var n=btoa(e+":"+t);return this.set("Authorization","Basic "+n),this},d.prototype.query=function(e){return"string"!=typeof e&&(e=u(e)),e&&this._query.push(e),this},d.prototype.field=function(e,t){return this._formData||(this._formData=new b.FormData),this._formData.append(e,t),this},d.prototype.attach=function(e,t,n){return this._formData||(this._formData=new b.FormData),this._formData.append(e,t,n||t.name),this},d.prototype.send=function(e){var t=i(e),n=this.getHeader("Content-Type");if(t&&i(this._data))for(var r in e)this._data[r]=e[r];else"string"==typeof e?(n||this.type("form"),n=this.getHeader("Content-Type"),"application/x-www-form-urlencoded"==n?this._data=this._data?this._data+"&"+e:e:this._data=(this._data||"")+e):this._data=e;return!t||o(e)?this:(n||this.type("json"),this)},d.prototype.callback=function(e,t){var n=this._callback;this.clearTimeout(),n(e,t)},d.prototype.crossDomainError=function(){var e=new Error("Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.");e.crossDomain=!0,e.status=this.status,e.method=this.method,e.url=this.url,this.callback(e)},d.prototype.timeoutError=function(){var e=this._timeout,t=new Error("timeout of "+e+"ms exceeded");t.timeout=e,this.callback(t)},d.prototype.withCredentials=function(){return this._withCredentials=!0,this},d.prototype.end=function(e){var t=this,n=this.xhr=y.getXHR(),i=this._query.join("&"),u=this._timeout,a=this._formData||this._data;this._callback=e||r,n.onreadystatechange=function(){if(4==n.readyState){var e;try{e=n.status}catch(r){e=0}if(0==e){if(t.timedout)return t.timeoutError();if(t.aborted)return;return t.crossDomainError()}t.emit("end")}};var s=function(e){e.total>0&&(e.percent=e.loaded/e.total*100),e.direction="download",t.emit("progress",e)};this.hasListeners("progress")&&(n.onprogress=s);try{n.upload&&this.hasListeners("progress")&&(n.upload.onprogress=s)}catch(c){}if(u&&!this._timer&&(this._timer=setTimeout(function(){t.timedout=!0,t.abort()},u)),i&&(i=y.serializeObject(i),this.url+=~this.url.indexOf("?")?"&"+i:"?"+i),n.open(this.method,this.url,!0),this._withCredentials&&(n.withCredentials=!0),"GET"!=this.method&&"HEAD"!=this.method&&"string"!=typeof a&&!o(a)){var f=this.getHeader("Content-Type"),p=this._parser||y.serialize[f?f.split(";")[0]:""];!p&&l(f)&&(p=y.serialize["application/json"]),p&&(a=p(a))}for(var h in this.header)null!=this.header[h]&&n.setRequestHeader(h,this.header[h]);return this.emit("request",this),n.send("undefined"!=typeof a?a:null),this},d.prototype.then=function(e,t){return this.end(function(n,r){n?t(n):e(r)})},y.Request=d,y.get=function(e,t,n){var r=y("GET",e);return"function"==typeof t&&(n=t,t=null),t&&r.query(t),n&&r.end(n),r},y.head=function(e,t,n){var r=y("HEAD",e);return"function"==typeof t&&(n=t,t=null),t&&r.send(t),n&&r.end(n),r},y.del=m,y["delete"]=m,y.patch=function(e,t,n){var r=y("PATCH",e);return"function"==typeof t&&(n=t,t=null),t&&r.send(t),n&&r.end(n),r},y.post=function(e,t,n){var r=y("POST",e);return"function"==typeof t&&(n=t,t=null),t&&r.send(t),n&&r.end(n),r},y.put=function(e,t,n){var r=y("PUT",e);return"function"==typeof t&&(n=t,t=null),t&&r.send(t),n&&r.end(n),r},e.exports=y},function(e,t){function n(e){return e?r(e):void 0}function r(e){for(var t in n.prototype)e[t]=n.prototype[t];return e}e.exports=n,n.prototype.on=n.prototype.addEventListener=function(e,t){return this._callbacks=this._callbacks||{},(this._callbacks["$"+e]=this._callbacks["$"+e]||[]).push(t),this},n.prototype.once=function(e,t){function n(){this.off(e,n),t.apply(this,arguments)}return n.fn=t,this.on(e,n),this},n.prototype.off=n.prototype.removeListener=n.prototype.removeAllListeners=n.prototype.removeEventListener=function(e,t){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var n=this._callbacks["$"+e];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+e],this;for(var r,o=0;or;++r)n[r].apply(this,t)}return this},n.prototype.listeners=function(e){return this._callbacks=this._callbacks||{},this._callbacks["$"+e]||[]},n.prototype.hasListeners=function(e){return!!this.listeners(e).length}},function(e,t){e.exports=function(e,t,n){for(var r=0,o=e.length,i=3==arguments.length?n:e[r++];o>r;)i=t.call(null,i,e[r],++r,e);return i}},function(e,t){}]); -------------------------------------------------------------------------------- /session-6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "session-6", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "clean": "rimraf dist", 9 | "fenix": "rimraf node_modules && npm i", 10 | "start": "webpack-dev-server" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "babel-cli": "6.4.5", 17 | "babel-loader": "6.2.3", 18 | "babel-polyfill": "6.3.14", 19 | "babel-preset-es2015": "6.3.13", 20 | "css-loader": "0.23.1", 21 | "extract-text-webpack-plugin": "1.0.1", 22 | "node-sass": "^3.4.2", 23 | "rimraf": "2.5.2", 24 | "sass-loader": "^3.1.2", 25 | "style-loader": "0.13.0", 26 | "superagent": "^1.7.2", 27 | "webpack": "1.12.13", 28 | "webpack-dev-server": "1.14.1", 29 | "webpack-merge": "0.7.3" 30 | }, 31 | "dependencies": { 32 | "underscore.string": "^3.2.3" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /session-6/src/components/card/_index.scss: -------------------------------------------------------------------------------- 1 | .Card { 2 | margin: 8px; 3 | position: relative; 4 | border-radius: 2px; 5 | overflow: hidden; 6 | background-color: #fafafa; 7 | height: 180px; 8 | width: 130px; 9 | transition: box-shadow .25s; 10 | box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12); 11 | 12 | &-content { 13 | padding: 20px; 14 | border-radius: 0 0 2px 2px; 15 | 16 | p { 17 | margin: 0; 18 | padding: 0; 19 | } 20 | } 21 | 22 | &-title { 23 | line-height: 10px; 24 | font-size: 18px; 25 | font-weight: 300; 26 | } 27 | 28 | &-image { 29 | display: block; 30 | border-radius: 2px 2px 0 0; 31 | position: relative; 32 | left: 0; 33 | right: 0; 34 | top: 0; 35 | bottom: 0; 36 | height: 130px; 37 | width: 100%; 38 | } 39 | } -------------------------------------------------------------------------------- /session-6/src/components/card/index.js: -------------------------------------------------------------------------------- 1 | import {Image, Div, Text, HtmlComponent} from '../html'; 2 | 3 | class Card extends HtmlComponent { 4 | constructor({name, image} = {}){ 5 | super({name, image}); 6 | this._name = name; 7 | this._image = image; 8 | } 9 | 10 | render() { 11 | const card = new Div('Card'); 12 | const cardContent = new Div('Card-content'); 13 | const title = new Div('Card-title'); 14 | const image = new Image({className: 'Card-image', src: this._image}); 15 | const name = new Text({text: this._name}); 16 | 17 | title.appendChild(name); 18 | cardContent.appendChild(title); 19 | card.appendChild(image); 20 | card.appendChild(cardContent); 21 | 22 | return card.render(); 23 | } 24 | }; 25 | 26 | export default Card; 27 | -------------------------------------------------------------------------------- /session-6/src/components/html/div.js: -------------------------------------------------------------------------------- 1 | import HtmlComponent from './htmlComponent'; 2 | 3 | export default class Div extends HtmlComponent { 4 | constructor(className){ 5 | super(className); 6 | this._className = className; 7 | this._children = new Set(); 8 | } 9 | 10 | appendChild(element){ 11 | this._children.add(element); 12 | } 13 | 14 | render(){ 15 | const div = document.createElement('div'); 16 | div.className = this._className; 17 | 18 | for(let child of this._children){ 19 | console.log(child) 20 | div.appendChild(child.render()) 21 | } 22 | 23 | return div; 24 | } 25 | } -------------------------------------------------------------------------------- /session-6/src/components/html/htmlComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface 3 | **/ 4 | export default class HtmlComponent { 5 | render(){ 6 | throw new Error('You must implement the render() method'); 7 | } 8 | } -------------------------------------------------------------------------------- /session-6/src/components/html/image.js: -------------------------------------------------------------------------------- 1 | import HtmlComponent from './htmlComponent'; 2 | 3 | export default class Image extends HtmlComponent { 4 | constructor({className, src}) { 5 | super({className, src}); 6 | this._src = src; 7 | this._className = className; 8 | } 9 | 10 | render() { 11 | const img = document.createElement('img'); 12 | const src = document.createAttribute('src'); 13 | src.value = `http://pokeapi.co/${this._src}`; 14 | img.setAttributeNode(src); 15 | img.className = this._className; 16 | return img; 17 | } 18 | }; -------------------------------------------------------------------------------- /session-6/src/components/html/index.js: -------------------------------------------------------------------------------- 1 | import Image from './image'; 2 | import Div from './div'; 3 | import Text from './text'; 4 | import HtmlComponent from './htmlComponent'; 5 | 6 | export {Image, Div, Text, HtmlComponent}; -------------------------------------------------------------------------------- /session-6/src/components/html/text.js: -------------------------------------------------------------------------------- 1 | import HtmlComponent from './htmlComponent'; 2 | 3 | export default class Text extends HtmlComponent { 4 | constructor({text}){ 5 | super({text}); 6 | this._text = text; 7 | } 8 | 9 | render(){ 10 | return document.createTextNode(this._text); 11 | } 12 | } -------------------------------------------------------------------------------- /session-6/src/domain/entity.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface 3 | * */ 4 | export default class Entity {} 5 | -------------------------------------------------------------------------------- /session-6/src/domain/factories/pokemon.js: -------------------------------------------------------------------------------- 1 | import PokemonListUseCase from '../pokemon/pokemonListUseCase'; 2 | import ApiPokemonRepository from '../pokemon/apiPokemonRepository'; 3 | import PokemonEntity from '../pokemon/pokemonEntity'; 4 | import SpriteEntity from '../pokemon/spriteEntity'; 5 | import superagent from 'superagent'; 6 | 7 | export default class PokemonFactory { 8 | 9 | static pokemonListUseCase() { 10 | return new PokemonListUseCase({repository: PokemonFactory.apiPokemonRepository()}); 11 | } 12 | 13 | static apiPokemonRepository() { 14 | return new ApiPokemonRepository(PokemonFactory.fetcher()); 15 | } 16 | 17 | static fetcher(){ 18 | return superagent; 19 | } 20 | 21 | static pokemonEntity({name, resource_uri, sprites} = {}){ 22 | return new PokemonEntity({ 23 | name, 24 | resource_uri, 25 | sprites: sprites && sprites.map(PokemonFactory.spriteEntity) 26 | }); 27 | } 28 | 29 | static spriteEntity({id, resource_uri, image, pokemon}){ 30 | return new SpriteEntity({id, resource_uri, image, pokemon: PokemonFactory.pokemonEntity(pokemon)}); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /session-6/src/domain/index.js: -------------------------------------------------------------------------------- 1 | import PokemonFactory from './factories/pokemon'; 2 | 3 | class Pokedex { 4 | constructor(){ 5 | this._deps = new Map(); 6 | 7 | this._deps.set('pokemon_list_use_case', PokemonFactory.pokemonListUseCase()); 8 | } 9 | 10 | get(key) { 11 | if(this._deps.has(key)) 12 | return this._deps.get(key); 13 | console.warn(`Service ${key} is not implemented in the current version of the domain`); 14 | } 15 | } 16 | 17 | export default new Pokedex(); 18 | -------------------------------------------------------------------------------- /session-6/src/domain/pokemon/apiPokemonRepository.js: -------------------------------------------------------------------------------- 1 | import PokemonRepository from './pokemonRepository'; 2 | import PokemonFactory from '../factories/pokemon'; 3 | 4 | /** 5 | * @implements PokemonRepository 6 | * */ 7 | export default class ApiPokemonRepository extends PokemonRepository { 8 | constructor(fetcher){ 9 | super(fetcher); 10 | this._fetcher = fetcher; 11 | } 12 | 13 | list({query = ''} = {}) { 14 | return new Promise((resolve, reject) => { 15 | this._fetcher.get('http://pokeapi.co/api/v1/pokemon') 16 | .query({ limit: 20 }) 17 | .end((err, resp) => { 18 | if(err){ 19 | reject(err); 20 | return; 21 | } 22 | try { 23 | resolve(JSON.parse(resp.text).objects.map(PokemonFactory.pokemonEntity)) 24 | } catch(err) { reject(err); } 25 | }); 26 | }); 27 | }; 28 | 29 | sprite({resource_uri} = {}){ 30 | return new Promise((resolve, reject) => { 31 | this._fetcher.get(`http://pokeapi.co${resource_uri}`) 32 | .end((err, resp) => { 33 | if(err) { 34 | reject(err); 35 | return; 36 | } 37 | try { 38 | resolve(PokemonFactory.spriteEntity(JSON.parse(resp.text))); 39 | } catch(err) { reject(err); } 40 | }) 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /session-6/src/domain/pokemon/pokemonEntity.js: -------------------------------------------------------------------------------- 1 | import Entity from '../entity'; 2 | import capitalize from 'underscore.string/capitalize'; 3 | 4 | export default class PokemonEntity extends Entity { 5 | constructor({name, resource_uri, sprites} = {}){ 6 | super({name, resource_uri}); 7 | 8 | this._name = name; 9 | this.resource_uri = resource_uri; 10 | this.sprites = sprites; 11 | } 12 | 13 | get name() { 14 | return capitalize(this._name); 15 | } 16 | 17 | set image(value) { 18 | this._image = value; 19 | } 20 | 21 | get image() { 22 | return this._image; 23 | } 24 | } -------------------------------------------------------------------------------- /session-6/src/domain/pokemon/pokemonListUseCase.js: -------------------------------------------------------------------------------- 1 | import UseCase from '../useCase'; 2 | 3 | /** 4 | * @implements UseCase 5 | * */ 6 | export default class PokemonListUseCase extends UseCase { 7 | 8 | constructor({repository} = {}) { 9 | super(repository); 10 | this.repository = repository; 11 | } 12 | 13 | execute({query = ''} = {}) { 14 | return new Promise((resolve, reject) => { 15 | this.repository.list({query}) 16 | .then((pokemons) => { 17 | Promise.all(pokemons.map(pokemon => 18 | this.repository.sprite({resource_uri: pokemon.sprites[0].resource_uri}) 19 | )) 20 | .then((sprites) => { 21 | return pokemons.map(pokemon => { 22 | pokemon.image = sprites.filter(s => s.pokemon.resource_uri === pokemon.resource_uri)[0].image; 23 | return pokemon; 24 | }) 25 | }) 26 | .then(pokemons => { 27 | resolve(pokemons); 28 | }) 29 | }) 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /session-6/src/domain/pokemon/pokemonRepository.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface 3 | * */ 4 | export default class PokemonRepository { 5 | list({query = ''} = {}) { 6 | throw new Error('PokemonRepository#list must be implemented'); 7 | } 8 | 9 | sprite({resource_uri} = {}){ 10 | throw new Error('PokemonRepository#sprite must be implemented'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /session-6/src/domain/pokemon/spriteEntity.js: -------------------------------------------------------------------------------- 1 | import Entity from '../entity'; 2 | 3 | export default class SpriteEntity extends Entity { 4 | constructor({id, image, resource_uri, pokemon} = {}) { 5 | super({id, image, resource_uri, pokemon}); 6 | this.id = id; 7 | this.image = image; 8 | this.resource_uri = resource_uri; 9 | this.pokemon = pokemon; 10 | } 11 | } -------------------------------------------------------------------------------- /session-6/src/domain/useCase.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface 3 | * */ 4 | export default class Service { 5 | execute() { 6 | throw new Error('Service#execute must be implemented'); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /session-6/src/index.js: -------------------------------------------------------------------------------- 1 | import Card from './components/card'; 2 | import Pokedex from './domain'; 3 | import './index.scss'; 4 | 5 | Pokedex.get('pokemon_list_use_case') 6 | .execute() 7 | .then((pokemons) => { 8 | return pokemons.map(p => new Card(p)) 9 | }) 10 | .then((cards) => { 11 | for(let card of cards) { 12 | document.body.appendChild(card.render()); 13 | } 14 | }); -------------------------------------------------------------------------------- /session-6/src/index.scss: -------------------------------------------------------------------------------- 1 | @import './components/card/index'; 2 | 3 | html { 4 | line-height: 1.5; 5 | font-family: "Roboto", sans-serif; 6 | font-weight: normal; 7 | font-size: 15px; 8 | } 9 | 10 | body { 11 | display: flex; 12 | flex-flow: row wrap; 13 | } 14 | 15 | a { 16 | text-decoration: none; 17 | } -------------------------------------------------------------------------------- /session-6/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | var merge = require('webpack-merge'); 5 | 6 | var APP_PATH = path.join(__dirname, '/src'); 7 | var TARGET = process.env.npm_lifecycle_event; 8 | 9 | var common = { 10 | context: APP_PATH, 11 | entry: './', 12 | output: { 13 | path: path.join(__dirname, 'dist'), 14 | filename: '[name].js', 15 | publicPath: 'http://localhost:3000/dist' 16 | }, 17 | module: { loaders: [{ 18 | test: /\.js$/, 19 | loaders: [ 'babel' ], 20 | exclude: /node_modules/ 21 | }] }, 22 | plugins: [] 23 | }; 24 | 25 | if(TARGET === 'start' || !TARGET) { 26 | module.exports = merge(common, { 27 | devServer: { 28 | port: 3000, 29 | stats: { colors: true }, 30 | inline: true, 31 | publicPath: '/dist/' 32 | }, 33 | module: { 34 | loaders: [{ 35 | test: /\.s?css$/, 36 | loaders: [ 'style-loader', 'css-loader', 'sass-loader' ], 37 | include: APP_PATH 38 | }] 39 | }, 40 | plugins: [ 41 | new webpack.HotModuleReplacementPlugin() 42 | ] 43 | }); 44 | } 45 | 46 | if(TARGET === 'build') { 47 | module.exports = merge(common, { 48 | module: { 49 | loaders: [{ 50 | test: /\.s?css$/, 51 | loader: ExtractTextPlugin.extract('css!sass'), 52 | include: APP_PATH 53 | }] 54 | }, 55 | plugins: [ 56 | new ExtractTextPlugin('[name].css', { 57 | allChunks: true 58 | }), 59 | new webpack.optimize.UglifyJsPlugin({ 60 | compress: { 61 | warnings: false 62 | } 63 | }) 64 | ] 65 | }); 66 | } 67 | --------------------------------------------------------------------------------