|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733 |
- <!doctype html><!-- This is a valid HTML5 document. -->
- <!-- Screen readers, SEO, extensions and so on. -->
- <html lang=fr>
- <!-- Has to be within the first 1024 bytes, hence before the <title>
- See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
- <meta charset=utf-8>
- <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
- <!-- The viewport meta is quite crowded and we are responsible for that.
- See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
- <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
- <!-- Required to make a valid HTML5 document. -->
- <title>The Two Pillars of JavaScript (archive) — David Larlet</title>
- <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
- <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
- <link rel="manifest" href="/manifest.json">
- <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
- <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
- <meta name="apple-mobile-web-app-title" content="David Larlet">
- <meta name="application-name" content="David Larlet">
- <meta name="msapplication-TileColor" content="#da532c">
- <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
- <meta name="theme-color" content="#f0f0ea">
- <!-- That good ol' feed, subscribe :p. -->
- <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
-
- <meta name="robots" content="noindex, nofollow">
- <meta content="origin-when-cross-origin" name="referrer">
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3">
-
- <style>
- /* http://meyerweb.com/eric/tools/css/reset/ */
- html, body, div, span,
- h1, h2, h3, h4, h5, h6, p, blockquote, pre,
- a, abbr, address, big, cite, code,
- del, dfn, em, img, ins,
- small, strike, strong, tt, var,
- dl, dt, dd, ol, ul, li,
- fieldset, form, label, legend,
- table, caption, tbody, tfoot, thead, tr, th, td,
- article, aside, canvas, details, embed,
- figure, figcaption, footer, header, hgroup,
- menu, nav, output, ruby, section, summary,
- time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
- }
- /* HTML5 display-role reset for older browsers */
- article, aside, details, figcaption, figure,
- footer, header, hgroup, menu, nav, section { display: block; }
- body { line-height: 1; }
- blockquote, q { quotes: none; }
- blockquote:before, blockquote:after,
- q:before, q:after {
- content: '';
- content: none;
- }
- table {
- border-collapse: collapse;
- border-spacing: 0;
- }
-
- /* http://practicaltypography.com/equity.html */
- /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
- /* https://www.filamentgroup.com/lab/js-web-fonts.html */
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
- font-weight: 300;
- font-style: normal;
- font-display: swap;
- }
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
- font-weight: 300;
- font-style: italic;
- font-display: swap;
- }
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
- font-weight: 700;
- font-style: normal;
- font-display: swap;
- }
-
- @font-face {
- font-family: 'ConcourseT3';
- src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
- url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
- font-weight: 300;
- font-style: normal;
- font-display: swap;
- }
-
-
- /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
- body {
- /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
- font-family: "EquityTextB", Palatino, serif;
- background-color: #f0f0ea;
- color: #07486c;
- font-kerning: normal;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: subpixel-antialiased;
- text-rendering: optimizeLegibility;
- font-variant-ligatures: common-ligatures contextual;
- font-feature-settings: "kern", "liga", "clig", "calt";
- }
- pre, code, kbd, samp, var, tt {
- font-family: 'TriplicateT4c', monospace;
- }
- em {
- font-style: italic;
- color: #323a45;
- }
- strong {
- font-weight: bold;
- color: black;
- }
- nav {
- background-color: #323a45;
- color: #f0f0ea;
- display: flex;
- justify-content: space-around;
- padding: 1rem .5rem;
- }
- nav:last-child {
- border-bottom: 1vh solid #2d7474;
- }
- nav a {
- color: #f0f0ea;
- }
- nav abbr {
- border-bottom: 1px dotted white;
- }
-
- h1 {
- border-top: 1vh solid #2d7474;
- border-bottom: .2vh dotted #2d7474;
- background-color: #e3e1e1;
- color: #323a45;
- text-align: center;
- padding: 5rem 0 4rem 0;
- width: 100%;
- font-family: 'ConcourseT3';
- display: flex;
- flex-direction: column;
- }
- h1.single {
- padding-bottom: 10rem;
- }
- h1 span {
- position: absolute;
- top: 1vh;
- left: 20%;
- line-height: 0;
- }
- h1 span a {
- line-height: 1.7;
- padding: 1rem 1.2rem .6rem 1.2rem;
- border-radius: 0 0 6% 6%;
- background: #2d7474;
- font-size: 1.3rem;
- color: white;
- text-decoration: none;
- }
- h2 {
- margin: 4rem 0 1rem;
- border-top: .2vh solid #2d7474;
- padding-top: 1vh;
- }
- h3 {
- text-align: center;
- margin: 3rem 0 .75em;
- }
- hr {
- height: .4rem;
- width: .4rem;
- border-radius: .4rem;
- background: #07486c;
- margin: 2.5rem auto;
- }
- time {
- display: bloc;
- margin-left: 0 !important;
- }
- ul, ol {
- margin: 2rem;
- }
- ul {
- list-style-type: square;
- }
- a {
- text-decoration-skip-ink: auto;
- text-decoration-thickness: 0.05em;
- text-underline-offset: 0.09em;
- }
- article {
- max-width: 50rem;
- display: flex;
- flex-direction: column;
- margin: 2rem auto;
- }
- article.single {
- border-top: .2vh dotted #2d7474;
- margin: -6rem auto 1rem auto;
- background: #f0f0ea;
- padding: 2rem;
- }
- article p:last-child {
- margin-bottom: 1rem;
- }
- p {
- padding: 0 .5rem;
- margin-left: 3rem;
- }
- p + p,
- figure + p {
- margin-top: 2rem;
- }
-
- blockquote {
- background-color: #e3e1e1;
- border-left: .5vw solid #2d7474;
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 1rem;
- margin: 1.5rem;
- }
- blockquote cite {
- font-style: italic;
- }
- blockquote p {
- margin-left: 0;
- }
-
- figure {
- border-top: .2vh solid #2d7474;
- background-color: #e3e1e1;
- text-align: center;
- padding: 1.5rem 0;
- margin: 1rem 0 0;
- font-size: 1.5rem;
- width: 100%;
- }
- figure img {
- max-width: 250px;
- max-height: 250px;
- border: .5vw solid #323a45;
- padding: 1px;
- }
- figcaption {
- padding: 1rem;
- line-height: 1.4;
- }
- aside {
- display: flex;
- flex-direction: column;
- background-color: #e3e1e1;
- padding: 1rem 0;
- border-bottom: .2vh solid #07486c;
- }
- aside p {
- max-width: 50rem;
- margin: 0 auto;
- }
-
- /* https://fvsch.com/code/css-locks/ */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: 1rem;
- line-height: calc( 1.5em + 0.2 * 1rem );
- }
- h1 {
- font-size: 1.9rem;
- line-height: calc( 1.2em + 0.2 * 1rem );
- }
- h2 {
- font-size: 1.6rem;
- line-height: calc( 1.3em + 0.2 * 1rem );
- }
- h3 {
- font-size: 1.35rem;
- line-height: calc( 1.4em + 0.2 * 1rem );
- }
- @media (min-width: 20em) {
- /* The (100vw - 20rem) / (50 - 20) part
- resolves to 0-1rem, depending on the
- viewport width (between 20em and 50em). */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
- margin-left: 0;
- }
- h1 {
- font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- h2 {
- font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- h3 {
- font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- }
- @media (min-width: 50em) {
- /* The right part of the addition *must* be a
- rem value. In this example we *could* change
- the whole declaration to font-size:2.5rem,
- but if our baseline value was not expressed
- in rem we would have to use calc. */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: calc( 1rem + .6 * 1rem );
- line-height: 1.5em;
- }
- p, li, pre, details {
- margin-left: 3rem;
- }
- h1 {
- font-size: calc( 1.9rem + 1.5 * 1rem );
- line-height: 1.2em;
- }
- h2 {
- font-size: calc( 1.5rem + 1.5 * 1rem );
- line-height: 1.3em;
- }
- h3 {
- font-size: calc( 1.35rem + 1.5 * 1rem );
- line-height: 1.4em;
- }
- figure img {
- max-width: 500px;
- max-height: 500px;
- }
- }
-
- figure.unsquared {
- margin-bottom: 1.5rem;
- }
- figure.unsquared img {
- height: inherit;
- }
-
-
-
- @media print {
- body { font-size: 100%; }
- a:after { content: " (" attr(href) ")"; }
- a, a:link, a:visited, a:after {
- text-decoration: underline;
- text-shadow: none !important;
- background-image: none !important;
- background: white;
- color: black;
- }
- abbr[title] { border-bottom: 0; }
- abbr[title]:after { content: " (" attr(title) ")"; }
- img { page-break-inside: avoid; }
- @page { margin: 2cm .5cm; }
- h1, h2, h3 { page-break-after: avoid; }
- p3 { orphans: 3; widows: 3; }
- img {
- max-width: 250px !important;
- max-height: 250px !important;
- }
- nav, aside { display: none; }
- }
-
- ul.with_columns {
- column-count: 1;
- }
- @media (min-width: 20em) {
- ul.with_columns {
- column-count: 2;
- }
- }
- @media (min-width: 50em) {
- ul.with_columns {
- column-count: 3;
- }
- }
- ul.with_two_columns {
- column-count: 1;
- }
- @media (min-width: 20em) {
- ul.with_two_columns {
- column-count: 1;
- }
- }
- @media (min-width: 50em) {
- ul.with_two_columns {
- column-count: 2;
- }
- }
-
- .gallery {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-around;
- }
- .gallery figure img {
- margin-left: 1rem;
- margin-right: 1rem;
- }
- .gallery figure figcaption {
- font-family: 'ConcourseT3'
- }
-
- footer {
- font-family: 'ConcourseT3';
- display: flex;
- flex-direction: column;
- border-top: 3px solid white;
- padding: 4rem 0;
- background-color: #07486c;
- color: white;
- }
- footer > * {
- max-width: 50rem;
- margin: 0 auto;
- }
- footer a {
- color: #f1c40f;
- }
- footer .avatar {
- width: 200px;
- height: 200px;
- border-radius: 50%;
- float: left;
- -webkit-shape-outside: circle();
- shape-outside: circle();
- margin-right: 2rem;
- padding: 2px 5px 5px 2px;
- background: white;
- border-left: 1px solid #f1c40f;
- border-top: 1px solid #f1c40f;
- border-right: 5px solid #f1c40f;
- border-bottom: 5px solid #f1c40f;
- }
- </style>
-
- <h1>
- <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
- The Two Pillars of JavaScript (archive)
- <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
- </h1>
- <section>
- <article>
- <h3><a href="https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3">Source originale du contenu</a></h3>
- <p name="b45e" id="b45e" class="graf--p graf--first">Before we get into this, allow me to introduce myself — you’re probably going to wonder who I think I am before this is over.</p>
-
- <p name="9935" id="9935" class="graf--p">I’m <strong class="markup--strong markup--p-strong">Eric Elliott</strong>, author of <strong class="markup--strong markup--p-strong">“Programming JavaScript Applications”</strong> <strong class="markup--strong markup--p-strong">(O’Reilly)</strong>, host of the <em class="markup--em markup--p-em">feature-length documentary film-in-production,</em> <strong class="markup--strong markup--p-strong">“Programming Literacy”</strong>, and creator of the <a target="_blank" href="http://ericelliottjs.com/" data-href="http://ericelliottjs.com/" class="markup--anchor markup--p-anchor" rel="nofollow"><strong class="markup--strong markup--p-strong">“Learn JavaScript with Eric Elliott”</strong></a><strong class="markup--strong markup--p-strong"> </strong>series of online JavaScript courses.</p>
-
- <p name="edcb" id="edcb" class="graf--p">I have contributed to software experiences for <strong class="markup--strong markup--p-strong">Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC, </strong>and top recording artists including <strong class="markup--strong markup--p-strong">Usher, Frank Ocean, Metallica,</strong> and many more.</p>
-
- <h4 name="0262" id="0262" class="graf--h4">Once Upon a Time</h4>
-
- <p name="f4e0" id="f4e0" class="graf--p">I was trapped in the darkness. I was blind — shuffling about, bumping into things, breaking things, and generally making an unholy mess of everything I touched.</p>
-
- <p name="49d1" id="49d1" class="graf--p">In the 90's, I was programming in C++, Delphi, and Java and writing 3D plugins for the software suite that eventually became Maya (used by lots of major motion picture studios to make summer blockbuster movies).</p>
-
- <p name="6b47" id="6b47" class="graf--p">Then it happened: The internet took off. Everybody started building websites, and after writing and editing a couple online magazines, a friend convinced me that the future of the web would be SaaS products (before the term was coined). I didn’t know it then, but that subtle course change transformed the way I think about programming on a fundamental level, because <em class="markup--em markup--p-em">if you want to make a good SaaS product, you have to learn JavaScript.</em></p>
-
- <p name="7211" id="7211" class="graf--p">Once I learned it, I never looked back. Suddenly, everything was easier. The software I made was more malleable. Code survived longer without being rewritten. Initially, I thought JavaScript was mostly UI scripting glue, but when I learned cookies and AJAX blew up, that transformed, too.</p>
-
- <p name="ac42" id="ac42" class="graf--p">I got addicted, and I couldn’t go back. JavaScript offers something other languages lack:</p>
-
- <blockquote name="9463" id="9463" class="graf--pullquote pullquote">Freedom!</blockquote>
-
- <p name="eaea" id="eaea" class="graf--p">JavaScript is one of the most important programming languages of all time, not simply because of it’s popularity, but because it popularized two features which are extremely important for the evolution of programming:</p>
-
- <ul class="postList"><li name="3d98" id="3d98" class="graf--li"><strong class="markup--strong markup--li-strong">Objects without classes</strong> (and prototypal inheritance aka OLOO — Objects Linking to Other Objects), and</li><li name="09e2" id="09e2" class="graf--li"><strong class="markup--strong markup--li-strong">Lambdas</strong> (with closure — the keys to functional programming)</li></ul>
-
- <p name="f8a1" id="f8a1" class="graf--p">Collectively, I like to call these paradigms <strong class="markup--strong markup--p-strong">the two pillars of JavaScript,</strong><em class="markup--em markup--p-em"> </em>and I’m not ashamed to admit that they’ve spoiled me. I don’t want to program in a language without them.</p>
-
- <p name="8a9c" id="8a9c" class="graf--p"><em class="markup--em markup--p-em">JavaScript will be remembered as one of the most influential languages ever created.</em> Lots of other languages have already copied one or the other, or both of the pillars, and the pillars have transformed the way we write applications, <em class="markup--em markup--p-em">even in other languages.</em></p>
-
- <p name="da48" id="da48" class="graf--p">Brendan Eich didn’t invent either of the pillars, but JavaScript exposed the programming masses to them. Both pillars are equally important, but I’m concerned that a large number of JavaScript programmers are completely missing one or both innovations, because JavaScript is pretty good at letting you code poorly if you don’t bother to learn it properly.</p>
-
- <p name="44a9" id="44a9" class="graf--p">This is actually a feature, because it makes it really easy to pick up JavaScript and start doing useful things with it, but that phase of your development as a JavaScript programmer <em class="markup--em markup--p-em">should last no more than a year.</em></p>
-
- <p name="1e20" id="1e20" class="graf--p">If you haven’t yet, <strong class="markup--strong markup--p-strong">it’s time to level up.</strong></p>
-
- <p name="5d45" id="5d45" class="graf--p">If you’re creating constructor functions and inheriting from them, you haven’t learned JavaScript. It doesn’t matter if you’ve been doing it since 1995. You’re failing to take advantage of JavaScript’s most powerful capabilities.</p>
-
- <p name="828b" id="828b" class="graf--p"><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">You’re working in the phony version of JavaScript that only exists to dress the language up like Java.</em></strong></p>
-
- <p name="1dac" id="1dac" class="graf--p">You’re coding in this amazing, game-changing, seminal programming language and <em class="markup--em markup--p-em">completely missing what makes it so cool and interesting.</em></p>
-
- <h3 name="284a" id="284a" class="graf--h3">We’re Constructing a Mess.</h3>
-
- <p name="d0e8" id="d0e8" class="graf--p graf--empty"><br/></p>
-
- <blockquote name="1693" id="1693" class="graf--blockquote graf--startsWithDoubleQuote">“Those who are not aware they are walking in darkness will never seek the light.” ~ Bruce Lee</blockquote>
-
- <p name="9ae3" id="9ae3" class="graf--p"><strong class="markup--strong markup--p-strong">Constructors violate the open/closed principle</strong> because they couple all callers to the details of how your object gets instantiated. Making an HTML5 game? Want to change from new object instances to use object pools so you can recycle objects and <a target="_blank" href="https://www.youtube.com/watch?v=RWmzxyMf2cE" data-href="https://www.youtube.com/watch?v=RWmzxyMf2cE" class="markup--anchor markup--p-anchor" rel="nofollow">stop the garbage collector from trashing your frame rate?</a> Too bad. You’ll either break all the callers, or you’ll end up with a hobbled factory function.</p>
-
- <p name="aa79" id="aa79" class="graf--p">If you return an arbitrary object from a constructor function, it will break your prototype links, and the <em class="markup--em markup--p-em">`this`</em> keyword will no longer be bound to the new object instance in the constructor. It’s also less flexible than a real factory function because you can’t use <em class="markup--em markup--p-em">`this`</em> at all in the factory; it just gets thrown away.</p>
-
- <p name="5208" id="5208" class="graf--p">Constructors that aren’t running in strict mode can be downright dangerous, too. If a caller forgets <em class="markup--em markup--p-em">`new`</em> and you’re not using <em class="markup--em markup--p-em">strict mode</em> or <em class="markup--em markup--p-em">ES6 classes</em> <em class="markup--em markup--p-em">[sigh]</em>, anything you assign to <em class="markup--em markup--p-em">`this`</em> will pollute the global namespace. That’s ugly.</p>
-
- <p name="7c90" id="7c90" class="graf--p">Prior to strict mode, this language glitch caused hard-to-find bugs at two different startups I worked for, during critical growth periods when we didn’t have a lot of extra time to chase down hard-to-find bugs.</p>
-
- <p name="594a" id="594a" class="graf--p">In JavaScript, <strong class="markup--strong markup--p-strong">factory functions</strong> are simply constructor functions <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">minus</em></strong> the <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">`new` </em>requirement,</strong> <strong class="markup--strong markup--p-strong">global pollution danger</strong> and <strong class="markup--strong markup--p-strong">awkward limitations</strong> (including that annoying initial capitalized letter convention).</p>
-
- <p name="8b23" id="8b23" class="graf--p"><strong class="markup--strong markup--p-strong">JavaScript doesn’t need constructor functions</strong> because <em class="markup--em markup--p-em">any function can return a new object. </em>With dynamic object extension, object literals and `<em class="markup--em markup--p-em">Object.create()`, </em>we have everything we need — with none of the mess. And <em class="markup--em markup--p-em">`this`</em> behaves just like it does in any other function. Hurray!</p>
-
- <h3 name="9ed4" id="9ed4" class="graf--h3">Welcome to the Seventh Circle of Hell.</h3>
-
- <p name="18a2" id="18a2" class="graf--p graf--empty"><br/></p>
-
- <blockquote name="a445" id="a445" class="graf--blockquote graf--startsWithDoubleQuote">“Quite frequently I am not so miserable as it would be wise to be.” ~ T.H. White</blockquote>
-
- <p name="d6bd" id="d6bd" class="graf--p">Everyone has heard the boiling frog anecdote: If you put a frog in boiling water, it will jump out. If you put the frog in cool water and gradually increase the heat, the frog will boil to death because it doesn’t sense the danger. In this story, we are the frogs.</p>
-
- <p name="3970" id="3970" class="graf--p">If <em class="markup--em markup--p-em">constructor</em> behavior is the <em class="markup--em markup--p-em">frying pan</em>, <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">classical inheritance</em></strong> isn’t <em class="markup--em markup--p-em">the fire;</em> <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">it’s the fire from Dante’s seventh circle of hell.</em></strong></p>
-
- <h4 name="aec9" id="aec9" class="graf--h4">The Gorilla / Banana problem:</h4>
-
- <p name="a781" id="a781" class="graf--p graf--empty"><br/></p>
-
- <blockquote name="508e" id="508e" class="graf--blockquote graf--startsWithDoubleQuote">“The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.” ~ Joe Armstrong</blockquote>
-
- <p name="d129" id="d129" class="graf--p">Classical Inheritance generally lets you inherit only from a single ancestor, forcing you into awkward taxonomies. I say awkward because without fail, <em class="markup--em markup--p-em">every OO design taxonomy I have ever seen in a large application was eventually wrong.</em></p>
-
- <p name="b5fe" id="b5fe" class="graf--p">Say you start with two classes: <em class="markup--em markup--p-em">Tool</em> and <em class="markup--em markup--p-em">Weapon</em>. You’ve already screwed up — <em class="markup--em markup--p-em">You can’t make the game “Clue.”</em></p>
-
- <h4 name="3ded" id="3ded" class="graf--h4">The Tight Coupling Problem</h4>
-
- <p name="a3e1" id="a3e1" class="graf--p graf--empty"><br/></p>
-
- <p name="b97f" id="b97f" class="graf--p"><em class="markup--em markup--p-em">The coupling between a child class and its parent is the tightest form of coupling in OO design. </em>That’s the opposite of reusable, modular code.</p>
-
- <p name="ad0c" id="ad0c" class="graf--p">Making <em class="markup--em markup--p-em">small changes </em>to a class creates <em class="markup--em markup--p-em">rippling side-effects </em>that break things that should be completely unrelated.</p>
-
- <h4 name="b1e7" id="b1e7" class="graf--h4">The Duplication by Necessity Problem</h4>
-
- <p name="5ba1" id="5ba1" class="graf--p graf--empty"><br/></p>
-
- <p name="ddc0" id="ddc0" class="graf--p">The obvious solution to taxonomy troubles is to go back in time, build up new classes with subtle differences by changing up what inherits from what — but it’s too tightly coupled to properly extract and refactor. You end up duplicating code instead of reusing it. You violate the <strong class="markup--strong markup--p-strong">DRY</strong> principle (Don’t Repeat Yourself).</p>
-
- <p name="b132" id="b132" class="graf--p">As a consequence, you keep growing your subtly different jungle of classes, and as you add inheritance levels, your classes get more and more arthritic and brittle. When you find a bug, you don’t fix it in one place. <em class="markup--em markup--p-em">You fix it everywhere.</em></p>
-
- <blockquote name="06aa" id="06aa" class="graf--blockquote graf--startsWithDoubleQuote">“Oops. Missed one.” — Every Classical OO programmer, ever.</blockquote>
-
- <p name="7f79" id="7f79" class="graf--p">This is known as <strong class="markup--strong markup--p-strong">the duplication by necessity problem </strong>in OO design circles.</p>
-
- <p name="1124" id="1124" class="graf--p"><strong class="markup--strong markup--p-strong">ES6 classes don’t fix any of these problems. </strong>ES6 makes them worse, because these <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">bad ideas </em></strong><em class="markup--em markup--p-em">will be officially blessed by the spec, </em>and written about in a thousand books and blog posts.</p>
-
- <p name="b086" id="b086" class="graf--p"><strong class="markup--strong markup--p-strong">The <em class="markup--em markup--p-em">`class` </em>keyword will probably be the most harmful feature in JavaScript. </strong>I have enormous respect for the brilliant and hard-working people who have been involved in the standardization effort, but even brilliant people occasionally do the wrong thing. Try adding .1 + .2 in your browser console, for instance. I still think Brendan Eich has contributed greatly to the web, to programming languages, and to computer science in general.</p>
-
- <p name="5bb1" id="5bb1" class="graf--p">P.S. Don’t use <em class="markup--em markup--p-em">`super` </em>unless you enjoy stepping through the debugger into multiple layers of inheritance abstraction.</p>
-
- <h4 name="c610" id="c610" class="graf--h4">The Fallout</h4>
-
- <p name="682d" id="682d" class="graf--p graf--empty"><br/></p>
-
- <p name="19ae" id="19ae" class="graf--p">These problems have a multiplying effect as your application grows, and eventually, the only solution is to rewrite the application from scratch or scrap it entirely — sometimes the business just needs to cut its losses.</p>
-
- <p name="d917" id="d917" class="graf--p">I have seen this process play out <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">again</em></strong><em class="markup--em markup--p-em">, and </em><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">again</em></strong><em class="markup--em markup--p-em">, </em><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">job</em></strong><em class="markup--em markup--p-em"> after </em><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">job</em></strong><em class="markup--em markup--p-em">, </em><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">project</em></strong><em class="markup--em markup--p-em"> after </em><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">project</em></strong><em class="markup--em markup--p-em">.</em> <em class="markup--em markup--p-em">Will we ever learn?</em></p>
-
- <p name="f140" id="f140" class="graf--p">At one company I worked for, <em class="markup--em markup--p-em">it caused a software release date to slip by an entire year for a rewrite.</em> I believe in <strong class="markup--strong markup--p-strong">updates, not rewrites.</strong> At another company I consulted for, <em class="markup--em markup--p-em">it almost caused the entire company to crash and burn.</em></p>
-
- <blockquote name="30ac" id="30ac" class="graf--pullquote pullquote"><strong class="markup--strong markup--pullquote-strong">These problems are not just a matter of taste or style. This choice can make or break your product.</strong></blockquote>
-
- <p name="4f7d" id="4f7d" class="graf--p">Large companies can usually chug along like nothing is wrong, but startups can’t afford to spin their wheels on problems like these while they’re struggling to find their product/market fit on a limited runway.</p>
-
- <p name="399b" id="399b" class="graf--p"><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">I’ve never seen any of the problems above in a modern code base that avoids classical inheritance altogether.</em></strong></p>
-
- <h3 name="04ab" id="04ab" class="graf--h3">Step into the light.</h3>
-
- <p name="2b66" id="2b66" class="graf--p graf--empty"><br/></p>
-
- <blockquote name="4e2c" id="4e2c" class="graf--blockquote graf--startsWithDoubleQuote">“Perfection is reached not when there is nothing more to add, but when there is nothing more to subtract.” ~ Antoine de Saint-Exupéry</blockquote>
-
- <p name="cd1f" id="cd1f" class="graf--p">A while back, I was working on a library to demonstrate how to use prototypal inheritance for my book, <a target="_blank" href="http://www.amazon.com/gp/product/1491950293?ie=UTF8&camp=213733&creative=393185&creativeASIN=1491950293&linkCode=shr&tag=eejs-20&linkId=ZURITP6JDCUKP6QF" data-href="http://www.amazon.com/gp/product/1491950293?ie=UTF8&camp=213733&creative=393185&creativeASIN=1491950293&linkCode=shr&tag=eejs-20&linkId=ZURITP6JDCUKP6QF" class="markup--anchor markup--p-anchor" rel="nofollow">“Programming JavaScript Applications”</a> (O’Reilly), when I settled on an interesting idea: a factory function that helps you produce factory functions that you can inherit from and compose together. I called the composable factories “stamps,” and the library, “Stampit.” The library is very small and simple. I gave a talk about Stampit at the O’Reilly Fluent Conference in 2013 (included here at the end of the article), and wrote a blog post about stamps (see below).</p>
-
- <p name="8078" id="8078" class="graf--p">There is a small, but steadily growing community of developers whose coding styles have been transformed by stamps. Stampit is in production use in multiple apps with millions of monthly active users.</p>
-
- <figure name="d01f" id="d01f" class="graf--figure postField--insetLeftImage"><div class="aspectRatioPlaceholder is-locked"><p class="aspect-ratio-fill"/><img class="graf-image" data-image-id="1*6432XLMVYjpOCisNaKEBgw.jpeg" data-width="1145" data-height="1145" data-action="zoom" data-action-value="1*6432XLMVYjpOCisNaKEBgw.jpeg" src="https://d262ilb51hltx0.cloudfront.net/max/600/1*6432XLMVYjpOCisNaKEBgw.jpeg"/></div></figure>
-
- <blockquote name="ef35" id="ef35" class="graf--blockquote graf--startsWithDoubleQuote">“I have been using Stampit a lot and really enjoy the power afforded by the simplicity in the separation of concerns between the types of prototypes as well as composable nature of stamps. Classical deep inheritance trees always bothered me, especially in the context of web development where business needs are often a moving target. The above mentioned talk and Stampit have inspired different thinking and allow me to do things that feel like interfaces without the overhead, or inherit private data with privileged methods from multiple sources. My prototypal inheritance is now strong, my objects have become shapeless, formless, like water. Keep up the great work, class sugar has nothing on this.” ~ Justin Schroeder, Senior Developer, Wrecking Ball Media Group</blockquote>
-
- <p name="5bf1" id="5bf1" class="graf--p">Stampit isn’t the only alternative, of course. Douglas Crockford doesn’t use <em class="markup--em markup--p-em">`new`</em> or <em class="markup--em markup--p-em">`this`</em> at all, instead opting for an entirely functional approach to code reuse.</p>
-
- <p name="c7fe" id="c7fe" class="graf--p">All his objects are just stateless bags of functions, or data-only objects like associative arrays with no methods. This works well unless you’re creating a hundreds of thousands of objects and you need your app to perform smoothly at or near realtime (think game engines, realtime signal processors, etc…). In those situations, delegating calls to methods can save you from a lot of manual memory management.</p>
-
- <p name="ba8f" id="ba8f" class="graf--p">Other good alternatives include making better use of JavaScript modules as an alternative to inheritance (I recommend npm and Node-style modules with Browserify), or simply cloning objects by copying properties from a source object to a new object (e.g. <em class="markup--em markup--p-em">`$.extend()`, `_.extend()`,</em> etc…).</p>
-
- <p name="1b5c" id="1b5c" class="graf--p">The copy mechanism is another form of prototypal inheritance. Sources of clone properties are a specific kind of prototype called <strong class="markup--strong markup--p-strong">exemplar prototypes, </strong>and cloning an exemplar prototype is known as <strong class="markup--strong markup--p-strong">concatenative inheritance.</strong></p>
-
- <p name="fe19" id="fe19" class="graf--p">Even if you follow Douglas Crockford’s advice and stop using <em class="markup--em markup--p-em">`this`, </em>you can still do things the prototypal way. Concatenative inheritance is possible because of a feature in JavaScript known as <strong class="markup--strong markup--p-strong">dynamic object extension: </strong>the ability to add to an object after it has been instantiated.</p>
-
- <p name="72d1" id="72d1" class="graf--p"><strong class="markup--strong markup--p-strong">You never need classes in JavaScript,</strong> and I have never seen a situation where class is a better approach than the alternatives. If you can think of any, leave a comment, but I’ve been making that challenge for years now, and <em class="markup--em markup--p-em">nobody has come up with a good use-case</em> — just flimsy arguments about micro-optimizations or style preferences.</p>
-
- <p name="8534" id="8534" class="graf--p">When I tell people that constructors and classical inheritance are bad, they get defensive. <em class="markup--em markup--p-em">I’m not attacking you. I’m trying to help you.</em></p>
-
- <p name="fabd" id="fabd" class="graf--p">People get attached to their programming style as if their coding style is how they express themselves. <em class="markup--em markup--p-em">Nonsense.</em></p>
-
- <blockquote name="340f" id="340f" class="graf--pullquote pullquote">What you make with your code is how you express yourself.</blockquote>
-
- <p name="17a1" id="17a1" class="graf--p">How it’s implemented doesn’t matter <strong class="markup--strong markup--p-strong">at all</strong> <em class="markup--em markup--p-em">unless it’s implemented poorly.</em></p>
-
- <blockquote name="a834" id="a834" class="graf--blockquote">The only thing that matters in software development is that your users love the software.</blockquote>
-
- <p name="12c4" id="12c4" class="graf--p">I can warn you that there’s a cliff ahead, but some people don’t believe there is danger until they experience it first hand. Don’t make that mistake; <em class="markup--em markup--p-em">the cost can be enormous.</em> <strong class="markup--strong markup--p-strong">This is your chance</strong> to learn from the mistakes that countless others have made <em class="markup--em markup--p-em">again</em> and <em class="markup--em markup--p-em">again</em> over the span of <em class="markup--em markup--p-em">decades.</em> Entire books have been written about these problems.</p>
-
- <p name="acaf" id="acaf" class="graf--p">The seminal <a target="_blank" href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&camp=213733&creative=393185&creativeASIN=0201633612&linkCode=shr&tag=eejs-20&linkId=5S2XB3C32NLP7IVQ" data-href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&camp=213733&creative=393185&creativeASIN=0201633612&linkCode=shr&tag=eejs-20&linkId=5S2XB3C32NLP7IVQ" class="markup--anchor markup--p-anchor" rel="nofollow">“Design Patterns” book by the Gang of Four</a> is built around two foundational principles:</p>
-
- <p name="23bc" id="23bc" class="graf--p graf--startsWithDoubleQuote"><em class="markup--em markup--p-em">“Program to an interface, not an implementation,”</em> and <em class="markup--em markup--p-em">“favor object composition over class inheritance.”</em></p>
-
- <p name="f411" id="f411" class="graf--p">Because child classes code to the implementation of the parent class, the second principle follows from the first, but it’s useful to spell it out.</p>
-
- <blockquote name="2f7f" id="2f7f" class="graf--pullquote pullquote">The seminal work on classical OO design is anti-class inheritance.</blockquote>
-
- <p name="5774" id="5774" class="graf--p">It contains a whole section of object creational patterns that exist solely to work around the limitations of constructors and class inheritance.</p>
-
- <p name="331c" id="331c" class="graf--p">Google <em class="markup--em markup--p-em">“new considered harmful,” “inheritance considered harmful,”</em> and <em class="markup--em markup--p-em">“super is a code smell.”</em> You’ll dig up dozens of articles from blog posts and respected publications like Dr. Dobb’s Journal dating back to before JavaScript was invented, all saying much the same thing: <em class="markup--em markup--p-em">`new`</em>, brittle classical inheritance taxonomies, and parent-child coupling (e.g. <em class="markup--em markup--p-em">`super`</em>) are recipes for disaster.</p>
-
- <p name="212b" id="212b" class="graf--p"><em class="markup--em markup--p-em">Even James Gosling, the creator of Java, admits that Java didn’t get objects right.</em></p>
-
- <p name="f34a" id="f34a" class="graf--p">Want to stick with JavaScript references? <a target="_blank" href="https://www.youtube.com/watch?v=bo36MrBfTk4" data-href="https://www.youtube.com/watch?v=bo36MrBfTk4" class="markup--anchor markup--p-anchor" rel="nofollow">Douglas Crockford</a> got <em class="markup--em markup--p-em">Object.create()</em> added to the language so he wouldn’t have to use <em class="markup--em markup--p-em">`new`</em>.</p>
-
- <p name="c349" id="c349" class="graf--p">Kyle Simpson (author, <a target="_blank" href="http://www.amazon.com/s/?_encoding=UTF8&camp=213733&creative=393193&linkCode=shr&tag=eejs-20&linkId=YSQEZLRZIRKYVBNS&rl=search-alias%3Daps&field-keywords=you%20don%27t%20know%20js&sprefix=you+don%27t+know+js%2Caps" data-href="http://www.amazon.com/s/?_encoding=UTF8&camp=213733&creative=393193&linkCode=shr&tag=eejs-20&linkId=YSQEZLRZIRKYVBNS&rl=search-alias%3Daps&field-keywords=you%20don%27t%20know%20js&sprefix=you+don%27t+know+js%2Caps" class="markup--anchor markup--p-anchor" rel="nofollow">“You Don’t Know JS”</a>) wrote a fascinating three part blog series on the topic called <a target="_blank" href="http://davidwalsh.name/javascript-objects" data-href="http://davidwalsh.name/javascript-objects" class="markup--anchor markup--p-anchor" rel="nofollow">“JS Objects: Inherited a Mess.”</a></p>
-
- <p name="654b" id="654b" class="graf--p">Kyle argues that prototypal inheritance is anti-class, that’s simpler and better than class. He even coined the term <strong class="markup--strong markup--p-strong">OLOO</strong> (Objects Linked to Other Objects) to clarify the distinction between prototype delegation and class inheritance.</p>
-
- <p name="f3b3" id="f3b3" class="graf--p graf--empty"><br/></p>
-
- <h2 name="a985" id="a985" class="graf--h2">Good code is simple.</h2>
-
- <p name="f64e" id="f64e" class="graf--p graf--empty"><br/></p>
-
- <blockquote name="d4ee" id="d4ee" class="graf--blockquote graf--startsWithDoubleQuote">“Simplicity is about subtracting the obvious and adding the meaningful.” ~ John Maeda</blockquote>
-
- <h4 name="f616" id="f616" class="graf--h4">As you strip constructors and classical inheritance out of JavaScript, it:</h4>
-
- <ul class="postList"><li name="db15" id="db15" class="graf--li"><strong class="markup--strong markup--li-strong">Gets simpler</strong> (Easier to read and to write. No more wrong design taxonomies.)</li><li name="24fb" id="24fb" class="graf--li"><strong class="markup--strong markup--li-strong">Gets more flexible</strong> (Switch from new instances to recycling object pools or proxies? No problem.)</li><li name="cf5f" id="cf5f" class="graf--li"><strong class="markup--strong markup--li-strong">Gets more powerful & expressive</strong> (Inherit from multiple ancestors? Inherit private state? No problem.)</li></ul>
-
- <h4 name="d03c" id="d03c" class="graf--h4">The Better Option</h4>
-
- <p name="b16a" id="b16a" class="graf--p graf--empty"><br/></p>
-
- <blockquote name="1bfe" id="1bfe" class="graf--blockquote graf--startsWithDoubleQuote">“If a feature is sometimes dangerous, and there is a better option, then always use the better option.” ~ Douglas Crockford</blockquote>
-
- <p name="67ef" id="67ef" class="graf--p">I’m not trying to take a useful tool away from you. I’m warning you that <em class="markup--em markup--p-em">what you think is a tool is actually a foot-gun.</em> In the case of constructors and classes, there are <em class="markup--em markup--p-em">several better options.</em></p>
-
- <p name="0b11" id="0b11" class="graf--p">Another common argument that programmers use is that it should be up to them how they express themselves, as if code style rises to the level of art or fashion. This argument is a purely emotional and irrational:</p>
-
- <p name="1a92" id="1a92" class="graf--p"><em class="markup--em markup--p-em">Your code isn’t the product of your self expression any more than a painter’s paintbrush is the product of their self expression. </em><strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">Code is the tool. The program is the product.</em></strong></p>
-
- <p name="55ff" id="55ff" class="graf--p">Yes, <em class="markup--em markup--p-em">some code is art in and of itself,</em> but if it doesn’t stand alone published on paper, <strong class="markup--strong markup--p-strong"><em class="markup--em markup--p-em">your code doesn’t fall into that category.</em></strong><em class="markup--em markup--p-em"> </em>Otherwise, as far as your users are concerned, <em class="markup--em markup--p-em">the code is a black box, and what they enjoy is the program.</em></p>
-
- <p name="0db8" id="0db8" class="graf--p">Good programming style requires that when you’re presented with a choice that’s elegant, simple, and flexible, or another choice that’s complex, awkward, and restricting, you choose the former. I know it’s popular to be open minded about language features, but <em class="markup--em markup--p-em">there is a right way and a wrong way.</em></p>
-
- <p name="cc68" id="cc68" class="graf--p"><strong class="markup--strong markup--p-strong">Choose the right way.</strong></p>
- </article>
- </section>
-
-
- <nav id="jumpto">
- <p>
- <a href="/david/blog/">Accueil du blog</a> |
- <a href="https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3">Source originale</a> |
- <a href="/david/stream/2019/">Accueil du flux</a>
- </p>
- </nav>
-
- <footer>
- <div>
- <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
- <p>
- Bonjour/Hi!
- Je suis <a href="/david/" title="Profil public">David Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
- Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
- </p>
- <p>
- Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
- </p>
-
- <p>
- Voici quelques articles choisis :
- <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
- <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
- <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
- <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
- <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
- <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
- <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
- <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
- <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
- <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
- <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
- <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
- <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
- <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
- <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
- et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
- </p>
- <p>
- On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
- </p>
- <p>
- Je ne traque pas ta navigation mais mon
- <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
- conserve des logs d’accès.
- </p>
- </div>
- </footer>
- <script type="text/javascript">
- ;(_ => {
- const jumper = document.getElementById('jumper')
- jumper.addEventListener('click', e => {
- e.preventDefault()
- const anchor = e.target.getAttribute('href')
- const targetEl = document.getElementById(anchor.substring(1))
- targetEl.scrollIntoView({behavior: 'smooth'})
- })
- })()
- </script>
|