Commit f2bf972dd80233cb168413d8a5cbed78b7e2d13f
1 parent
d5d1cc9a32
Exists in
master
go
Showing 12 changed files with 582 additions and 27 deletions
- cours-06.html
- cours-07.html
- index.html
- js-examples/js-functions-superpow.js
- js-examples/js-functions-this-minimal.js
- js-examples/js-functions-this.js
- js-examples/js-functions-thisarrow-noparam-tentation-pb.js
- js-examples/js-functions-thisarrow.js
- media/frflag.svg
- raw/cours-10-13.zip
- raw/cours-10-20-api.zip
- raw/cours-10-20-js.zip
cours-06.html
View file @
f2bf972
... | ... | @@ -362,33 +362,6 @@ |
362 | 362 | - @anim: .anonymous>span:nth-of-type(5), .anonymous>span:nth-of-type(6) |
363 | 363 | |
364 | 364 | |
365 | -## Objets et Classes JS {libyli} | |
366 | -- JS n'est pas un langage orienté classe (Java) | |
367 | -- JS est un langage à prototype | |
368 | -- Très dynamique | |
369 | -- Attention à `this` (≠ Java) | |
370 | - - un objet « contexte » | |
371 | - - pas nécessairement d'un type donné (comme la classe) | |
372 | -- Plus flexible que les langages à classes | |
373 | -- Le mot clé `class` arrive en ES6 ;-( | |
374 | - | |
375 | - | |
376 | -## ES6 (ES2015) {libyli} | |
377 | -- Syntaxe : class | |
378 | - - `constructor()`, `super()` | |
379 | - - `get`, `set` | |
380 | -- Syntaxes | |
381 | - - Modifieurs et portées de variables : const, var, val, let | |
382 | - - *Arrow Functions* et gestion du `this` | |
383 | - - Interpolation de string `\`Hello ${name}\`` | |
384 | - - Propriétés : raccourcis, méthodes, prop. construire (`[ «» ] : «»`) | |
385 | - - Construction et déconstruction pour listes et objets (avec valeur par défaut et y compris en param) | |
386 | - - *Rest* et *Spread* avec `...` (y compris en paramètre, syntactic sugar pour `arguments`) | |
387 | - - Paramètres par défaut `a=2` | |
388 | -- Autres : modules, generator | |
389 | -- <a href="http://es6-features.org/" target="_blank">etc.</a> | |
390 | - | |
391 | - | |
392 | 365 | |
393 | 366 | |
394 | 367 |
cours-07.html
View file @
f2bf972
1 | +<!DOCTYPE html> | |
2 | +<html> | |
3 | + <head> | |
4 | + <meta charset="utf-8"> | |
5 | + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
6 | + | |
7 | + <title>Programmation Web Avancée vue, vuex, REST</title> | |
8 | + <meta name="cours-n" content="7"> | |
9 | + | |
10 | + <meta name="author" content="Rémi Emonet"> | |
11 | + <meta name="venue" content="PWA M1 DSC"> | |
12 | + <meta name="date" content="2017"> | |
13 | + <meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien"> | |
14 | + | |
15 | + <style type="text/css"> | |
16 | + .slide.densish>ul {font-size: 70%;} | |
17 | + .commented-fs p {margin: 1em; } | |
18 | + .frflag { | |
19 | + background-image: url(media/frflag.svg); | |
20 | + width: 1em; | |
21 | + height: .75em; | |
22 | + display: inline-block; | |
23 | + background-size: contain; | |
24 | + } | |
25 | + </style> | |
26 | + | |
27 | + <!-- | |
28 | + <script src="deck.js/extensions/includedeck/load.js"></script> | |
29 | + <script src="extensions/slides-dev.js"></script> | |
30 | + --> | |
31 | + <script src="extensions/deck-packed.js"></script> | |
32 | + <script src="extensions/slides.js"></script> | |
33 | + <script>go()</script> | |
34 | + </head> | |
35 | + | |
36 | +<body> | |
37 | + | |
38 | +<div class="deck-container"> | |
39 | + | |
40 | + <div class="deck-loading-splash" style="background: black; color: chartreuse;"><span class="vcenter" style="font-size: 30px; font-family: Arial; ">Please wait, while our marmots are preparing the hot chocolate…</span></div> | |
41 | + | |
42 | +<section class="smart"> | |
43 | + | |
44 | +# @chunk: chunks/title.md | |
45 | + | |
46 | +# Questions ? <br/> Commentaires ? {no-print} | |
47 | + | |
48 | +# @chunk: chunks/objectives.md | |
49 | + | |
50 | +## Programmation Web Avancée <span>{var-cours-n}</span> : Plan {#plan overview} | |
51 | +- Javascript {rappeljs} | |
52 | +- Vue : les bases {vue} | |
53 | +- Vue : composants {vuecomp} | |
54 | +- Principes REST {rest} | |
55 | +- Serveur REST en Spring {springrest} | |
56 | +- Client REST JSON en Vue {restjs} | |
57 | +# @copy:#plan | |
58 | + | |
59 | + | |
60 | + | |
61 | +<!-- ################################### --> | |
62 | +# @copy:#plan: %+class:inred: .rappeljs | |
63 | + | |
64 | +# <a href="cours-06.html#slide-59" target="_blank">slides précédents</a> | |
65 | + | |
66 | +## Fonctions JS {libyli} | |
67 | +- Fonction nommée « classique » en JavaScript | |
68 | +```javascript | |
69 | +function toto(a,b) { | |
70 | + return a+b; | |
71 | +} | |
72 | +alert(toto(1,3)); | |
73 | +{dense slide} | |
74 | +``` | |
75 | +- Fonction JavaScript : objet de première classe | |
76 | +```javascript | |
77 | +var f = function(a) { | |
78 | + return a*a; | |
79 | +} | |
80 | +alert(f(2)); | |
81 | +var squares = [1,2,3].map(f); | |
82 | +{dense slide firstorder} | |
83 | +``` | |
84 | +- @anim: .firstorder>span:nth-of-type(4) | .firstorder>span:nth-of-type(5) | |
85 | +- Fonction anonyme | |
86 | +```javascript | |
87 | +var squares = [1,2,3].map(function(a) { | |
88 | + return a*a; | |
89 | +}); | |
90 | + | |
91 | +setTimeout(function() { alert("Hello"); }, | |
92 | + 3000); | |
93 | +{dense slide anonymous} | |
94 | +``` | |
95 | +- @anim: .anonymous>span:nth-of-type(5), .anonymous>span:nth-of-type(6) | |
96 | + | |
97 | + | |
98 | +## Objets et Classes JS {libyli} | |
99 | +- JS n'est pas un langage orienté classe (Java) | |
100 | +- JS est un langage à prototype | |
101 | +- Très dynamique | |
102 | +- Attention à `this` (≠ Java) | |
103 | + - un objet « contexte » | |
104 | + - pas nécessairement d'un type donné (comme la classe) | |
105 | +- Plus flexible que les langages à classes | |
106 | +- Le mot clé `class` arrive en ES6 ;-( | |
107 | + | |
108 | + | |
109 | +## ES6 (ES2015) {libyli} | |
110 | +- Syntaxe : class | |
111 | + - `constructor()`, `super()` | |
112 | + - `get`, `set` | |
113 | +- Syntaxes | |
114 | + - Modifieurs et portées de variables : const, var, val, let | |
115 | + - *Arrow Functions* et gestion du `this` | |
116 | + - Interpolation de string `̀ Hello ${name}̀ ` (backticks) | |
117 | + - Propriétés : raccourcis, méthodes, prop. construire (`[ «» ] : «»`) | |
118 | + - Construction et déconstruction pour listes et objets (avec valeur par défaut et y compris en param) | |
119 | + - *Rest* et *Spread* avec `...` (y compris en paramètre, syntactic sugar pour `arguments`) | |
120 | + - Paramètres par défaut `a=2` | |
121 | +- Autres : modules, generator | |
122 | +- <a href="http://es6-features.org/" target="_blank">etc.</a> | |
123 | + | |
124 | +## Gestion du `this` et *Arrow Functions* (ES6) {libyli} | |
125 | +- Attention à `this` (≠ Java) | |
126 | + - un objet « contexte » variable | |
127 | + - pas nécessairement d'un type donné (comme la classe) | |
128 | +```javascript | |
129 | +var o = { | |
130 | + i: 10000, | |
131 | + test: function() { | |
132 | + | |
133 | + this.incr = function() { | |
134 | + this.i += 1; | |
135 | + console.log(this.i); | |
136 | + }; | |
137 | + | |
138 | + this.incr2 = () => { | |
139 | + this.i += 1; | |
140 | + console.log(this.i); | |
141 | + }; | |
142 | + | |
143 | + this.incr(); | |
144 | + this.incr2(); | |
145 | + setTimeout(this.incr, 300); // executer 300 ms plus tard | |
146 | + // TODO: .bind(this) | |
147 | + setTimeout(this.incr2, 600); // executer 600 ms plus tard | |
148 | + }, | |
149 | +}; | |
150 | + | |
151 | +o.test(); | |
152 | +{slide dense} | |
153 | +``` | |
154 | + | |
155 | +<!-- ################################### --> | |
156 | +# @copy:#plan: %+class:inred: .vue | |
157 | + | |
158 | +# Sans <span style="font-size: 50%">et avec</span> Vue :<br/> des champs synchronisés | |
159 | + | |
160 | +## Ce qu'on a utilisé | |
161 | +- Javascript | |
162 | + - `Array.from()`, `document.querySelectorAll`, `.forEach` | |
163 | + - `Math.random()` | |
164 | + - `.oninput`, `.tagName`, `.value`, `.textContent` | |
165 | +- CSS (`background`, `border`, `padding`) | |
166 | + | |
167 | +## Vue / Vuex | |
168 | +- Vue | |
169 | + - framework léger pour applications interactives coté client | |
170 | + - similarité avec Angular, React, Ember, ... | |
171 | + - approche composant avec bindings | |
172 | + - <a href="https://vuejs.org/v2/guide/" target="_blank">https://vuejs.org/v2/guide/</a> | |
173 | + - <a href="https://fr.vuejs.org/v2/guide/index.html" target="_blank">https://fr.vuejs.org/v2/guide/index.html</a> <span class="frflag"/> | |
174 | +- Vuex | |
175 | + - <a href="https://vuex.vuejs.org/en/" target="_blank">https://vuex.vuejs.org/en/</a> | |
176 | + - <a href="https://vuex.vuejs.org/fr/" target="_blank">https://vuex.vuejs.org/fr/</a> <span class="frflag"/> | |
177 | + | |
178 | +# <span style="font-size: 50%">Sans et</span> avec Vue :<br/> des champs synchronisés | |
179 | + | |
180 | +## Vue : Principes {libyli} | |
181 | +- Données observables, rendu automatiquement à jour | |
182 | +- Template HTML+CSS | |
183 | + - avec des moustaches `{{ ... }}{}` (n'importe quelle expression ecmascript) | |
184 | + - avec des directives *vue*, éléments avec des attributs `v-...` | |
185 | + - accès automatique au *ViewModel* | |
186 | +- Objet javascript de type `Vue` | |
187 | +```javascript | |
188 | +var vm = new Vue({ | |
189 | + el: ..., // selecteur CSS de l'élément à traiter | |
190 | + data: { // objet contenant l'état / les données / le ViewModel | |
191 | + ... | |
192 | + }, | |
193 | + methods: { // les actions / le comportement | |
194 | + ... | |
195 | + }, | |
196 | + computed: { // des fonctions, chacune renvoie une propriété calculée | |
197 | + ... // possibilité de {get: ..., set: ...} pour un mutateur calculé | |
198 | + }, | |
199 | + watch: { // listener quand une des propriétés de data change | |
200 | + ... | |
201 | + } | |
202 | +}); | |
203 | +{slide dense} | |
204 | +``` | |
205 | + | |
206 | +## Vue : Liaison unidirectionnelle {libyli} | |
207 | +- Comme les moustaches mais pour des attributs | |
208 | +- Utlisation de `v-bind:...` ou `:...` | |
209 | +- Cas des attributs booléen (présent ou non dans le DOM), e.g. `:disabled="ind==0"` | |
210 | + | |
211 | + | |
212 | +## Vue : Liaison avec des formulaires {libyli} | |
213 | +- Pour les éléments éditables (input, select ou textarea) | |
214 | +- Liaison bidirectionnelle (de la propriété `value` de ces éléments) | |
215 | +- Attribut `v-model="..."` | |
216 | +- Valeur : nom de la propriété de l'état | |
217 | +- Modificateurs en suffixe `.lazy`, `.number`, `.trim` | |
218 | + | |
219 | +## Vue : Gestion des événements {libyli} | |
220 | +- Événements avec attributs `v-on:...` (ou `@...`) | |
221 | +- Valeur de l'attribut | |
222 | + - nom de la méthode | |
223 | + - ou, code à exécuter | |
224 | +- Modificateurs en suffixe | |
225 | + - gestion de l'événement : `.stop`, `.prevent`, `.once`, ... | |
226 | + - pour les touches et/ou click souris : `.shift`, `.ctrl`, `.exact`, ..., | |
227 | + - pour spécifier une touche : `.enter`, `.up`, `.space`, `.65`, ..., | |
228 | + - pour spécifier un bouton de la souris : `.left`, `.middle`, `.right` | |
229 | + | |
230 | +``` | |
231 | +<a v-on:click="go" v-on:mousemove.ctrl="go()">click ou ctrl+mouvement</a> | |
232 | + | |
233 | +<a @click="go" @mousemove.ctrl="go()">click ou ctrl+mouvement</a> | |
234 | +{slide denser} | |
235 | +``` | |
236 | + | |
237 | +## Vue : conditions et itérations {libyli} | |
238 | +- Affichage conditionnel avec `v-if="..."` | |
239 | + - expression booléene décidant du rendu ou non de l'élément | |
240 | + - NB: l'élément n'est alors pas dans le DOM | |
241 | +- Affichage en boucle (comme Thymeleaf) avec `v-for="vvv in lll"` | |
242 | + - nom de variable arbitraire | |
243 | + - possibilité d'avoir auss l'indice avec `(vvv, iii) in lll` | |
244 | + | |
245 | +## Vue : Autre | |
246 | +- Variables de contexte selon les cas: `$index` (boucles), `$event` (listener), ... | |
247 | + | |
248 | + | |
249 | + | |
250 | + | |
251 | + | |
252 | +<!-- ################################### --> | |
253 | +# @copy:#plan: %+class:inred: .vuecomp | |
254 | + | |
255 | +## Vue : Composants {libyli} | |
256 | +- But | |
257 | + - encapsuler un rendu et/ou comportement | |
258 | + - créer ses propres éléments, par ex, `〈pwa year="2017"〉Rocks〈/pwa〉{dense}` | |
259 | +- Fonction `Vue.component` | |
260 | + - `props`: liste des attributs attendus | |
261 | + - `template`: template HTML | |
262 | + - attention, `data` doit être une fonction (si présent) | |
263 | +``` | |
264 | +Vue.component('nom-du-tag', { | |
265 | + props: ['msg'], | |
266 | + template: '<div>{{ msg }}</div>', | |
267 | + data: function () { | |
268 | + return { | |
269 | + ... | |
270 | + } | |
271 | + }, | |
272 | + }); | |
273 | +{slide} | |
274 | +``` | |
275 | +- Utilisation | |
276 | +``` | |
277 | + <nom-du-tag msg="Salut"></nom-du-tag> | |
278 | + <nom-du-tag v-bind:msg="leMessage"></nom-du-tag> | |
279 | +{slide} | |
280 | +``` | |
281 | + | |
282 | +## Vue : Émettre des événements depuis un composant {libyli} | |
283 | +- Dans le composant | |
284 | + - utilisation de la fonction `$emit` | |
285 | + - par ex : `$emit('truc')` | |
286 | +- Dans le parent, ecoute classique | |
287 | + - par ex : `v-on:truc` ou `@truc` | |
288 | +- Possibilité d'utiliser `v-model` (bidirectionnel) | |
289 | + - avoir une prop `value` | |
290 | + - émettre des événements `input` (`this.$emit('input', v)`) | |
291 | + | |
292 | +## Vue : à voir | |
293 | +- composants dans un fichier `.vue` (pas de `template:'....'`) | |
294 | +- transition / animations | |
295 | +- packaging | |
296 | +- vue cli : ligne de commande | |
297 | +- vuex : gestion d'état centralisé | |
298 | +- routeur : url, bookmarking, deep linking | |
299 | +- directives perso | |
300 | + | |
301 | +<!-- ################################### --> | |
302 | +# @copy:#plan: %+class:inred: .rest | |
303 | + | |
304 | +# Principes REST : *Representational State Transfer* | |
305 | + | |
306 | +## *Representational State Transfer* {libyli} | |
307 | +- <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">Thèse de Roy T. Fielding</a> (et <a href="http://opikanoba.org/tr/fielding/rest/">[fr]</a>) | |
308 | +- Un style d'architecture | |
309 | + - un ensemble de ressources | |
310 | + - des liens entre ces ressources | |
311 | + - comme une bonne application Web | |
312 | + - Hypermedia as the engine of application state (HATEOAS) {slide} // important : le client choisi ce qu'il fait, le serveur guide | |
313 | +- Propriété et objectifs | |
314 | + - performance et passage à l'échelle // cacheable | |
315 | + - simplicité et évolutivité | |
316 | +- Principes {libyli} | |
317 | + - client-serveur, *stateless* (sans état), couches (cache, sécurité, ...) // ne sait pas si on parle au serveur directement | |
318 | + - ressources auto-décrites avec identifiant et métadonnées, HATEOAS | |
319 | +- <a href="http://www.figer.com/Publications/REST.htm">Résumé en Français</a> | |
320 | + | |
321 | +## *RESTful HTTP APIs* : REST sur HTTP {libyli} // RESTful (adjectif de REST) | |
322 | +- Ressource : identifiant et représentation | |
323 | + - URI (*Unique Resource Identifier*), `https://github.com/apache/spark {dense}` | |
324 | + - métadonnées, ex : `Content-Type: text/html{dense}`, `Content-Encoding: gzip{dense}` | |
325 | + - données, ex : HTML gzippé | |
326 | +- {no} | |
327 | + - NB : pas de verbes ou actions dans les URI // capital ! | |
328 | + - ok : `https://github.com/repositories` | |
329 | + - ko : `https://github.com/createNewRepo?name=pwa` | |
330 | +- Protocole *stateless* : HTTP avec méthodes HTTP {libyli} | |
331 | + - GET : sûre (sans effets de bords) | |
332 | + - récupère la représentation d'une ressource | |
333 | + - liste le contenu d'une collection | |
334 | + - DELETE : idempotente (même résultat si appliqué plusieurs fois) | |
335 | + - supprime une ressource existante | |
336 | + - supprime une collection | |
337 | + - PUT : idempotente | |
338 | + - remplace ou met à jour une ressource | |
339 | + - remplace ou met à jour une collection | |
340 | + - POST : | |
341 | + - crée une nouvelle entrée dans une collection | |
342 | + | |
343 | + | |
344 | + | |
345 | + | |
346 | + | |
347 | +<!-- ################################### --> | |
348 | +# @copy:#plan: %+class:inred: .springrest | |
349 | + | |
350 | +# <a href="https://spring.io/guides/tutorials/react-and-spring-data-rest/" target="_blank">(Tutoriel Spring+REST+React)</a> | |
351 | + | |
352 | +## Création d'un Modèle REST en Spring {libyli} | |
353 | +- {no} | |
354 | + - But : partager un modèle JPA en REST, au format JSON | |
355 | +- Étapes | |
356 | + - modèle : entités JPA | |
357 | + - service : repository `JpaRepository` (ou `CrudRepository`) | |
358 | + - `spring-data-rest-webmvc` (dépendance maven) | |
359 | + - ou à la main avec `@RestController`, `@Valid`, `RequestMethod.*` | |
360 | + - (configuration : `spring.data.rest.basePath=/api`) | |
361 | + - si client à une autre url : *Cross-origin resource sharing* (<a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a>) | |
362 | +- Test simplifiés | |
363 | +``` | |
364 | + curl -X GET http://localhost:8080/api/hotels | |
365 | + curl -X POST http://localhost:8080/api/hotels -H "Content-Type: application/json" -d '{"name":"ibis", "nrooms":444}' | |
366 | + curl -X GET http://localhost:8080/api/hotels | |
367 | + curl -X GET http://localhost:8080/api/hotels/ibis | |
368 | + curl -X DELETE http://localhost:8080/api/hotels/ibis | |
369 | + curl -X GET http://localhost:8080/api/hotels | |
370 | +{denser slide} | |
371 | +``` | |
372 | +- {no} | |
373 | + - Let's do it ! (hotels) | |
374 | + - (plugin JSONView + cfg content `application/hal+json`) | |
375 | + | |
376 | +<!-- ################################### --> | |
377 | +# @copy:#plan: %+class:inred: .restjs | |
378 | + | |
379 | +# à venir | |
380 | + | |
381 | + | |
382 | + | |
383 | + | |
384 | +</section> | |
385 | + | |
386 | + <!-- deck.status snippet --> | |
387 | + <p class="deck-status deck-progress-10"> <span class="deck-status-current"></span> / <span class="deck-status-total"></span> − <span class="var-author">will be replaced by the author</span> − <span class="var-title">will be replaced by the title</span></p> | |
388 | + | |
389 | + <a data-progress-size=": spe.top(15, 555); height: 45*designRatio; left: slide.right - 90*designRatio; width: 90*designRatio" class="ccby" href="http://en.wikipedia.org/wiki/Creative_Commons_license" title="This work is under CC-BY licence." target="_blank"></a> | |
390 | + | |
391 | + <a class="ujm" data-progress-size=": spe.top(15, 525); height: 65*designRatio; left: slide.left; width: 130*designRatio" target="_blank"></a> | |
392 | + | |
393 | +</div> | |
394 | +<!-- clicky Cla --> | |
395 | +<script type="text/javascript"> | |
396 | +var clicky_site_ids = clicky_site_ids || []; | |
397 | +clicky_site_ids.push(100779706); | |
398 | +(function() { | |
399 | + var s = document.createElement('script'); | |
400 | + s.type = 'text/javascript'; | |
401 | + s.async = true; | |
402 | + s.src = '//static.getclicky.com/js'; | |
403 | + ( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s ); | |
404 | +})(); | |
405 | +</script> | |
406 | +<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100779706ns.gif" /></p></noscript> | |
407 | + | |
408 | + | |
409 | +<!-- Histats.com START (aync)--> | |
410 | +<script type="text/javascript">var _Hasync= _Hasync|| []; | |
411 | +_Hasync.push(['Histats.start', '1,2767123,4,0,0,0,00010000']); | |
412 | +_Hasync.push(['Histats.fasi', '1']); | |
413 | +_Hasync.push(['Histats.track_hits', '']); | |
414 | +(function() { | |
415 | +var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true; | |
416 | +hs.src = ('http://s10.histats.com/js15_as.js'); | |
417 | +(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs); | |
418 | +})();</script> | |
419 | +<noscript><a href="http://www.histats.com" target="_blank"><img src="http://sstatic1.histats.com/0.gif?2767123&101" alt="javascript hit counter" border="0"></a></noscript> | |
420 | +<!-- Histats.com END --> | |
421 | +</body> | |
422 | +</html> |
index.html
View file @
f2bf972
... | ... | @@ -57,6 +57,9 @@ |
57 | 57 | <div> |
58 | 58 | <a class="tile" data-code-date="09-13"></a> |
59 | 59 | <a class="tile" data-code-date="09-29"></a> |
60 | + <a class="tile" data-code-date="10-13"></a> | |
61 | + <a class="tile" data-code-date="10-20-js"></a> | |
62 | + <a class="tile" data-code-date="10-20-api"></a> | |
60 | 63 | </div> |
61 | 64 | <!-- |
62 | 65 | <a href="raw/cours-2.zip">Fichiers HTML et CSS du cours</a> |
js-examples/js-functions-superpow.js
View file @
f2bf972
1 | + | |
2 | + | |
3 | +const superpow = (f, n) => (x) => { | |
4 | + var i = n; // copy to avoid sharing | |
5 | + var r = f(x); | |
6 | + while (i>1) { | |
7 | + i--; | |
8 | + r = f(r); | |
9 | + } | |
10 | + return r; | |
11 | +}; | |
12 | + | |
13 | +const f = (x) => x*x; | |
14 | +const f3 = superpow(f, 3) | |
15 | + | |
16 | +console.log(f3(2)) | |
17 | +console.log(f3(2)) | |
18 | + | |
19 | +console.log([1, 2, 3, 4, 5].map(f3)) | |
20 | + | |
21 | +console.log([1, 2, 3, 4, 5].map( superpow(f, 2) )) |
js-examples/js-functions-this-minimal.js
View file @
f2bf972
1 | +var o = { | |
2 | + i: 10000, | |
3 | + test: function() { | |
4 | + | |
5 | + this.incr = function() { | |
6 | + this.i += 1; | |
7 | + console.log(this.i); | |
8 | + }; | |
9 | + | |
10 | + this.incr2 = () => { | |
11 | + this.i += 1; | |
12 | + console.log(this.i); | |
13 | + }; | |
14 | + | |
15 | + this.incr(); | |
16 | + this.incr2(); | |
17 | + setTimeout(this.incr, 300); // executer 300 ms plus tard | |
18 | + // TODO: .bind(this) | |
19 | + setTimeout(this.incr2, 600); // executer 600 ms plus tard | |
20 | + }, | |
21 | +}; | |
22 | + | |
23 | +o.test(); |
js-examples/js-functions-this.js
View file @
f2bf972
1 | +var o = { | |
2 | + i: 10000, | |
3 | + | |
4 | + test: function() { | |
5 | + console.log("START", this.constructor.name, this.i); | |
6 | + | |
7 | + const incr = function() { | |
8 | + this.i += 1; | |
9 | + console.log("FUNCT", this.constructor.name, this.i); | |
10 | + }; | |
11 | + const incrArrow = () => { | |
12 | + this.i += 1; | |
13 | + console.log("ARROW", this.constructor.name, this.i); | |
14 | + }; | |
15 | + | |
16 | + console.log(); | |
17 | + incr(); | |
18 | + incrArrow(); | |
19 | + console.log(); | |
20 | + | |
21 | + setTimeout(incr, 250); // this?! | |
22 | + setTimeout(incrArrow, 500); // ok | |
23 | + | |
24 | + setTimeout(incr.bind(this), 750); // ok | |
25 | + setTimeout(incrArrow.bind(this), 1000); // ok (useless) | |
26 | + | |
27 | + setTimeout(function() { incr(); }, 1250); // KO | |
28 | + setTimeout(() => { incr(); }, 1500); // KO | |
29 | + }, | |
30 | +}; | |
31 | + | |
32 | +o.test(); |
js-examples/js-functions-thisarrow-noparam-tentation-pb.js
View file @
f2bf972
1 | +var o = { | |
2 | + démarrer: function() { // méthode | |
3 | + | |
4 | + this.i = 10000; | |
5 | + this.onAjouter1 = function() { // fonction traditionnelle | |
6 | + this.i += 1; | |
7 | + console.log(this.i); | |
8 | + }; | |
9 | + | |
10 | + this.onAjouter2 = function() { // fonction avec bind | |
11 | + this.i += 1; | |
12 | + console.log(this.i); | |
13 | + }.bind(this); | |
14 | + | |
15 | + this.onAjouter3 = () => { // arrow function | |
16 | + this.i += 1; | |
17 | + console.log(this.i); | |
18 | + }; | |
19 | + | |
20 | + | |
21 | + } | |
22 | +}; | |
23 | + | |
24 | +// simuler des événements, de suite ou venant d'ailleurs | |
25 | +o.démarrer(); | |
26 | +o.onAjouter1(); | |
27 | +o.onAjouter2(); | |
28 | +o.onAjouter3(); | |
29 | +setTimeout( function(){ o.onAjouter1(); }, 50); | |
30 | +setTimeout( function(){ o.onAjouter2(); }, 100); | |
31 | +setTimeout( function(){ o.onAjouter3(); }, 150); | |
32 | +setTimeout( () => { o.onAjouter1(); }, 200); | |
33 | +setTimeout( () => { o.onAjouter2(); }, 250); | |
34 | +setTimeout( () => { o.onAjouter3(); }, 300); | |
35 | +setTimeout( o.onAjouter1, 1000); | |
36 | +setTimeout( o.onAjouter2, 1500); | |
37 | +setTimeout( o.onAjouter3, 2000); |
js-examples/js-functions-thisarrow.js
View file @
f2bf972
1 | +var o = { | |
2 | + démarrer: function() { // méthode | |
3 | + | |
4 | + this.i = 10000; | |
5 | + this.onAjouter1 = function(v) { // fonction traditionnelle | |
6 | + this.i += v; | |
7 | + console.log(this.i); | |
8 | + }; | |
9 | + | |
10 | + this.onAjouter2 = function(v) { // fonction avec bind | |
11 | + this.i += v; | |
12 | + console.log(this.i); | |
13 | + }.bind(this); | |
14 | + | |
15 | + this.onAjouter3 = (v) => { // arrow function | |
16 | + this.i += v; | |
17 | + console.log(this.i); | |
18 | + }; | |
19 | + | |
20 | + | |
21 | + } | |
22 | +}; | |
23 | + | |
24 | +// simuler des événements, de suite ou venant d'ailleurs | |
25 | +o.démarrer(); | |
26 | +o.onAjouter1(1); | |
27 | +o.onAjouter2(2); | |
28 | +o.onAjouter3(4); | |
29 | +setTimeout( function(){ o.onAjouter1(8); }, 500); | |
30 | +setTimeout( function(){ o.onAjouter2(16); }, 1000); | |
31 | +setTimeout( function(){ o.onAjouter3(32); }, 1500); | |
32 | +setTimeout( () => { o.onAjouter1(64); }, 2000); | |
33 | +setTimeout( () => { o.onAjouter2(128); }, 2500); | |
34 | +setTimeout( () => { o.onAjouter3(256); }, 3000); |
media/frflag.svg
View file @
f2bf972
1 | +<svg xmlns="http://www.w3.org/2000/svg" height="480" width="640" viewBox="0 0 640 480"> | |
2 | + <g fill-rule="evenodd" stroke-width="1pt"> | |
3 | + <path fill="#fff" d="M0 0h640v480H0z"/> | |
4 | + <path fill="#00267f" d="M0 0h213.337v480H0z"/> | |
5 | + <path fill="#f31830" d="M426.662 0H640v480H426.662z"/> | |
6 | + </g> | |
7 | +</svg> |
raw/cours-10-13.zip
View file @
f2bf972
raw/cours-10-20-api.zip
View file @
f2bf972
raw/cours-10-20-js.zip
View file @
f2bf972