A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>JS Objects: Inherited a Mess (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="http://davidwalsh.name/javascript-objects">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. JS Objects: Inherited a Mess (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="http://davidwalsh.name/javascript-objects">Source originale du contenu</a></h3>
  445. <h3>JS Objects: TL;DR</h3>
  446. <p>&#13;
  447. <p>JavaScript has been plagued since the beginning with misunderstanding and awkwardness around its "prototypal inheritance" system, mostly due to the fact that "inheritance" isn't how JS works at all, and trying to do that only leads to gotchas and confusions that we have to pave over with user-land helper libs. Instead, embracing that JS has "behavior delegation" (merely delegation links between objects) fits naturally with how JS syntax works, which creates more sensible code without the need of helpers.</p>&#13;
  448. <p>When you set aside distractions like mixins, polymorphism, composition, classes, constructors, and instances, and only focus on the objects that link to each other, you gain a powerful tool in behavior delegation that is easier to write, reason about, explain, and code-maintain. Simpler is better. JS is "objects-only" (OO). Leave the classes to those other languages!</p>&#13;
  449. &#13;
  450. <h3>Due Thanks</h3>&#13;
  451. <p>I'd like to thank the following amazing devs for their generous time in feedback/tech review of this article series: David Bruant, Hugh Wood, Mark Trostler, and Mark McDonnell. I am also honored that David Walsh wanted to publish these articles on his fantastic blog.</p>&#13;
  452. &#13;
  453. <h3>Complete Series</h3>&#13;
  454. &#13;
  455. </div>&#13;
  456. &#13;
  457. <blockquote><p>year 2013: Haskell people are still writing monad tutorials, JavaScript people are still trying to explain inheritance.</p>&#13;
  458. &#13;
  459. <p>— Vyacheslav Egorov (@mraleph) <a rel="nofollow" href="https://twitter.com/mraleph/status/322843655381590016">April 12, 2013</a></p></blockquote>&#13;
  460. &#13;
  461. <p>As sad a criticism on JS as that quote is, it's quite true. (I have no perspective on Haskell or Monads, so I'm only talking about the JS and inheritance part). Of all the confusing and, depending on your biases, "bad", parts of this JS language, the behaviors of <code>this</code> and the <code>[[Prototype]]</code> chain have remained some of the most elusive to explain and use accurately.</p>&#13;
  462. &#13;
  463. <p>As a bit of background, I've been developing JS full time since 2007. The first major epiphany I had back then was the understanding of how closures work, and how they enable the classic module pattern. The first open-source project I wrote (early 2008) was <a rel="nofollow" href="https://github.com/flensed/flXHR">flXHR</a>, a cross-domain Ajax <a rel="nofollow" href="https://twitter.com/SlexAxton/status/257543702124306432">prollyfill</a> using the standard Ajax (XHR) interface (via a hidden flash element) that relied heavily upon the module pattern.</p>&#13;
  464. &#13;
  465. <p>It's quite possibly my "ah-ha!" moment around the module pattern that satisfied me enough that I never really felt a strong need to also apply the "inheritance" pattern to my JS design.</p>&#13;
  466. &#13;
  467. <p>Nevertheless, like most JS developers, I've read lots of blogs and books over the years that have tried (and mostly failed) to explain the appeal and mystery that is "JavaScript inheritance" (aka, "prototypal inheritance").</p>&#13;
  468. &#13;
  469. <p>But if it's so hard to understand, and even harder to actually do correctly, the <em>point</em> yet eludes me. And apparently I'm not alone in that frustration.</p>&#13;
  470. &#13;
  471. <h2>OO in JavaScript</h2>&#13;
  472. <p>In traditional <a rel="nofollow" href="http://en.wikipedia.org/wiki/Object-oriented_programming">Object-oriented languages</a>, the <a rel="nofollow" href="http://www.cs.bu.edu/teaching/cpp/inheritance/intro/">syntax of classes</a> matches the semantics. You can express the object-oriented concepts of classes, inheritance, and polymorphism directly and explicitly using the language's syntax. There's no need to use some helper library to fake your way into OO-like behavior through work-arounds of other language facilities.</p>&#13;
  473. &#13;
  474. <p>JavaScript on the other hand has <a rel="nofollow" href="https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript">a set of syntax that looks somewhat OO</a>, but which behaves in frustratingly different ways (which we will cover throughout this article series). As a result, the common way that you implement OO patterns in JS is through any of a variety of user-land helper libraries which let you express the desired semantic relationships between your "objects". The reason most JS developers use them is because the underlying JS syntax makes those semantic expressions awkward. It's nice to just let a library handle paving over the confusing syntax hiccups.</p>&#13;
  475. &#13;
  476. <p>Libraries like jQuery are useful because they hide the ugly details of dealing with <strong>cross-browser differences in JS engines</strong>. But these OO-helper libraries are different: they're going to great lengths to <strong>hide the true nature of JavaScript's OO mechanisms</strong>, instead masking them in a set of patterns that are more familiar to other languages.</p>&#13;
  477. &#13;
  478. <p>At this point of understanding, we should really ask ourselves: is the difficulty of <a rel="nofollow" href="http://javascript.crockford.com/inheritance.html">expressing classes and inheritance in pure JavaScript</a> a failure of the language (one which can <a rel="nofollow" href="http://prototypejs.org/learn/class-inheritance">temporarily</a> be <a rel="nofollow" href="http://mootools.net/docs/core/Class/Class">solved</a> with <a rel="nofollow" href="http://ejohn.org/blog/simple-javascript-inheritance/">user libraries</a>and ultimately solved by <a rel="nofollow" href="http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes">additions to the language like <code>class { .. }</code></a> syntax), <a rel="nofollow" href="https://c9.io/site/blog/2011/11/the-time-has-come-to-add-classes-to-javascript/">as many</a> devs <a rel="nofollow" href="http://www.nczonline.net/blog/2012/10/16/does-javascript-need-classes/">feel</a>, or is it something deeper? Is it indicative of a more fundamental disparity, that we're trying to <a rel="nofollow" href="http://www.kirupa.com/html5/objects_classes_javascript.htm">do something in JS</a> that it's<a rel="nofollow" href="http://webreflection.blogspot.com/2010/01/better-javascript-classes.html">just not meant to do</a>?</p>&#13;
  479. &#13;
  480. <p><a rel="nofollow" href="http://www.2ality.com/2011/11/javascript-classes.html">Not everyone</a> drank the JS classes kool-aid, so the rest of this article series will favor a different perspective.</p>&#13;
  481. <h2>Blueprint</h2>&#13;
  482. <p>One of the most common metaphors used in <a rel="nofollow" href="http://www.tutorialspoint.com/cplusplus/cpp_inheritance.htm">traditional class/inheritance OO</a> is that the <a rel="nofollow" href="http://msdn.microsoft.com/en-us/library/ee5edha0%28v=vs.80%29.aspx">class represents a "blueprint"</a> for a house to be built, but once you instantiate that class, you are basically copying all the characteristics from the blueprint into the actual built house. This metaphor partially matches, to an extent, what actually happens at a language level when the code is compiled, in that it sort-of flattens the definition of a class (sans "virtual" methods) inheritance hierarchy into the instance.</p>&#13;
  483. &#13;
  484. <p>Of course, a main pillar of <a rel="nofollow" href="http://www.alexonlinux.com/how-inheritance-encapsulation-and-polymorphism-work-in-cpp">inheritance-oriented coding is overriding and polymorphism</a>, which allows an object to<em>automatically</em> access the most descendant definition for a method, but also to use <code>super</code>-style relative references to access ancestor (aka "virtual") versions of the <em>same-named</em> method. In those cases, the compiler maintains lookup tables for the virtual methods, but it flattens out the non-virtual parts of the class/inheritance definition. The compiler can determine a lot about what needs to be preserved and not and highly optimize the definition structure it creates in the compiled code.</p>&#13;
  485. &#13;
  486. <p>For our purposes, we can think of traditional class-inheritance as basically a flattening "copy" of behavior down the chain to the instance. Here's a diagram to illustrate the inheritance relationship between a parent/base class<code>Foo</code>, and child class <code>Bar</code>, and then instances of each, respectively named <code>foo1</code>, <code>foo2</code>, <code>bar1</code>, and<code>bar2</code>. Visually, the arrows (aka, "copying") point from left-to-right and top-to-bottom:</p>&#13;
  487. &#13;
  488. <p><a rel="nofollow" href="http://davidwalsh.name/demo/InheritanceArrows.png" target="_blank"><img alt="Inheritance Arrows" src="http://davidwalsh.name/demo/InheritanceArrows.png"/></a></p>&#13;
  489. <h2>What's in a name?</h2>&#13;
  490. <p>Despite the borrowed implications of the common name "prototypal inheritance", JavaScript's mechanism works quite differently, which we'll see in just a moment.</p>&#13;
  491. &#13;
  492. <p>Both <a rel="nofollow" href="http://dictionary.reference.com/browse/inheritance?s=t">definitionally</a> ("...characteristics transmitted from parent to offspring") and behaviorally (as described above), "inheritance" is most closely associated with the idea of "copying" from parent to child.</p>&#13;
  493. &#13;
  494. <p>When you then take "inheritance" and apply it to a mechanism which has some very different behavior, you are asking for the confusion which has plagued "JavaScript inheritance" <a rel="nofollow" href="https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript">documentation</a>, <a rel="nofollow" href="http://blog.rjzaworski.com/2013/03/composition-in-javascript/">education</a>, and <a rel="nofollow" href="http://tobyho.com/2011/11/11/js-object-inheritance/">usage</a> for nearly 2 decades.</p>&#13;
  495. &#13;
  496. <p>To try to wade through this mess, let's set aside the label "inheritance" and its implications for JS, and hopefully we can arrive at something that is both conceptually more accurate and functionally more useful.</p>&#13;
  497. <h2>A.B.D's: Always Be Delegating</h2>&#13;
  498. <p>JavaScript's OO-like property mechanism for <a rel="nofollow" href="http://www.ecma-international.org/ecma-262/5.1/#sec-8.6">objects</a> is notated by <code>[[Prototype]]</code>, which is the internal characteristic of <strong>any object</strong> called its prototype-chain -- a special link to another object. It's kind of like a scope mechanism, in that the <code>[[Prototype]]</code> linkage <a rel="nofollow" href="http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.2">describes which alternate object should be referred to</a> if you request a property or method on your object which doesn't exist.</p>&#13;
  499. &#13;
  500. <p>In other words, you're indicating an object to <strong>delegate</strong> behavior to if that behavior isn't defined on the object in question.</p>&#13;
  501. &#13;
  502. <p>The above class-oriented <code>Foo</code> and <code>Bar</code> example, expressed in JS, relates object <code>Bar.prototype</code> to<code>Foo.prototype</code>, and then the <code>foo1</code>, <code>foo2</code>, <code>bar1</code> and <code>bar2</code> objects to their respective <code>[[Prototype]]</code>s. The arrows (not copies but live-links) point in a right-to-left, bottom-to-top fashion in JS:</p>&#13;
  503. &#13;
  504. <p><a rel="nofollow" href="https://dl.dropboxusercontent.com/u/2474669/jsdiagrams/DelegationArrows.png" target="_blank"><img alt="Delegation Arrows" src="http://davidwalsh.name/demo/DelegationArrows.png"/></a></p>&#13;
  505. &#13;
  506. <p>"Behavior delegation" is a more accurate term to describe JavaScript's <code>[[Prototype]]</code>. This is not just a matter of word semantics, it's a fundamentally different type of functionality.</p>&#13;
  507. &#13;
  508. <p>If you try to illustrate behavior delegation in terms of the "blueprint" metaphor, you quickly see how it totally breaks down. There's no way that my home, lacking a guest bedroom, could simply refer to another house, or to the original blueprints, to provide a bedroom for my mother-in-law when she comes to visit. Though the outcomes you can achieve have <strong><em>some</em></strong> respective similarities, the concepts of "inheritance" and "behavior delegation" <em>are quite different</em>.</p>&#13;
  509. &#13;
  510. <p>Some devs insist that "delegation" is just the dynamic version of "inheritance", like two sides of the same coin, but I see them <strong>as orthagonal systems</strong>.</p>&#13;
  511. &#13;
  512. <h3>How to delegate?</h3>&#13;
  513. <p>We'll revisit this later in the article series, but <a rel="nofollow" href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create"><code>Object.create(..)</code> was added to ES5</a> to assist with creating an object and then optionally linking its <code>[[Prototype]]</code> to another object. The link that is created is a delegation link, as opposed to an inheritance-by-copy.</p>&#13;
  514. &#13;
  515. <p><strong>Note:</strong> Once an object has its <code>[[Prototype]]</code> chain set at its creation, it <em>should</em> for the most part be considered set in stone and not changeable. Technically, browsers which support <a rel="nofollow" href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/proto">the <code><strong>proto</strong></code> property</a>, a public representation of the internal link, allow you to change at any time where an object is linked to. However, this practice is littered with landmines and generally frowned upon -- it's almost certainly something you'd want to<strong>avoid</strong> in your code.</p>&#13;
  516. &#13;
  517. <h2>Spade a Spade</h2>&#13;
  518. <p>You've seen how the mechanisms in JavaScript are comparitively different from the mechanisms in other languages. But is it ok to just hand-waive over these differences so we can keep using the term "inheritance" for JS?</p>&#13;
  519. &#13;
  520. <p>The fact is, it's just <strong>not</strong> an accurate usage of the term. By insisting that JavaScript has "inheritance", we're really saying that the meaning of the word "inheritance" doesn't matter, or is rather soft.</p>&#13;
  521. &#13;
  522. <p>JS doesn't statically analyze what parts of an inheritance chain it can safely flatten out <strong>and copy</strong>, it maintains links to the entire delegation chain throughout runtime, <strong>as distinct objects</strong>, which means our code can take advantage of <a rel="nofollow" href="http://michaux.ca/articles/early-mixins-late-mixins">a variety of powerful "late binding" dynamic patterns</a>.</p>&#13;
  523. &#13;
  524. <p>If we keep trying to mimic inheritance in JavaScript (syntax hurdles be damned), we get <em>distracted</em> and <strong>miss out on <em>all that power</em> that was built into our language from the start</strong>.</p>&#13;
  525. &#13;
  526. <p>I say: let's call it what it is, and stop trying to pile on JavaScript these other concepts that the "inheritance" label implies.&#13;
  527. </p><h2>So What?</h2>&#13;
  528. <p>So far, I've tried to identify some misconceptions about JS's <code>[[Prototype]]</code> mechanism and how "inheritance" is not a helpful label.</p>&#13;
  529. &#13;
  530. <p>You may still be skeptical why it <em>actually</em> matters what we call this OO-like mechanism in JS? In the <a href="http://davidwalsh.name/javascript-objects-distractions">next part</a> of the article series, I'm going to address many of the trappings of traditional "class-based" programming which I think are distractions that lead us to missing out on the essence of how JS objects interoperate. In fact, we could even say that <a rel="nofollow" href="http://www.infoq.com/presentations/Classes-Are-Premature-Optimization">classes/inheritance are a premature optimization</a> for JavaScript.</p>&#13;
  531. &#13;
  532. <p>Clearing those distractions out of the way leads us to <a href="http://davidwalsh.name/javascript-objects-deconstruction">part 3</a>, where we'll see a simpler and more robust pattern for our JS code, and more importantly, <strong>our code will actually match our semantics</strong> <em>without</em> us having to jump through hoops to hide the ugly mismatches.</p></p>
  533. </article>
  534. </section>
  535. <nav id="jumpto">
  536. <p>
  537. <a href="/david/blog/">Accueil du blog</a> |
  538. <a href="http://davidwalsh.name/javascript-objects">Source originale</a> |
  539. <a href="/david/stream/2019/">Accueil du flux</a>
  540. </p>
  541. </nav>
  542. <footer>
  543. <div>
  544. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  545. <p>
  546. Bonjour/Hi!
  547. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  548. 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>).
  549. </p>
  550. <p>
  551. 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>.
  552. </p>
  553. <p>
  554. Voici quelques articles choisis :
  555. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  556. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  557. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  558. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  559. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  560. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  561. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  562. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  563. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  564. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  565. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  566. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  567. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  568. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  569. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  570. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  571. </p>
  572. <p>
  573. 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>.
  574. </p>
  575. <p>
  576. Je ne traque pas ta navigation mais mon
  577. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  578. conserve des logs d’accès.
  579. </p>
  580. </div>
  581. </footer>
  582. <script type="text/javascript">
  583. ;(_ => {
  584. const jumper = document.getElementById('jumper')
  585. jumper.addEventListener('click', e => {
  586. e.preventDefault()
  587. const anchor = e.target.getAttribute('href')
  588. const targetEl = document.getElementById(anchor.substring(1))
  589. targetEl.scrollIntoView({behavior: 'smooth'})
  590. })
  591. })()
  592. </script>