Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
I didn't know that!
Search
stefan judis
July 19, 2018
Technology
1k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
I didn't know that!
stefan judis
July 19, 2018
More Decks by stefan judis
See All by stefan judis
Back to boring (part 2)
stefanjudis
0
380
Playwright can do this?
stefanjudis
0
250
Things you should know about Frontend Development in 2022
stefanjudis
0
560
Throw yourself out there for fun and profit
stefanjudis
0
140
Back to Boring
stefanjudis
1
540
Wanna scale up? Make sure your CMS is ready for it!
stefanjudis
0
290
Did we(b development) lose the right direction?
stefanjudis
6
2.2k
Regular expressions – my secret love
stefanjudis
1
1.1k
Write a Function
stefanjudis
0
630
Other Decks in Technology
See All in Technology
【CEDEC2026】『Relink』を拡張せよ - 『GRANBLUE FANTASY: Relink - Endless Ragnarok』の開発速度と品質を守るCI運用
cygames
PRO
0
150
システム思考で問題に対処する
yussak
0
230
ホームラボ紹介
y_sera15
0
140
[ChatGPT Work LT]事務作業が苦手な人のための バックオフィスの「半」自動化
chimaki_iot
0
270
サイバー捜査員研修(前半)
nomizone
1
1.9k
老害フォレンジッカーはAI羊の夢を見るか?
tadmaddad
0
310
Breaking the Seal: Static Deobfuscation of Compiled V8 JavaScript Bytecode Malware
hshrzd
0
700
【CEDEC2026】『GRANBLUE FANTASY: Relink - Endless Ragnarok』のバトル制作事例 ~最高のキャラゲーを目指して~
cygames
PRO
0
240
SO-101×VLAによる3色キューブのピック&プレース
abeja
0
180
Model Studio CLI × Token Plan
maigo999
0
130
オートロックマンションなのに、各部屋は施錠なし!? 攻撃者が組織内ネットワークで大暴れする理由 / The Front Door Is Locked, but the Rooms Are Wide Open: Why Attackers Move Freely Inside Enterprise Networks
nttcom
1
1.6k
ボトムアップ文化が強い組織で セキュリティをどう根付かせていくかの現在進行形の話 / Making Security Stick in a Bottom-Up Organization
yamaguchitk333
0
210
Featured
See All Featured
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
630
Discover your Explorer Soul
emna__ayadi
2
1.2k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
230
Raft: Consensus for Rubyists
vanstee
141
7.6k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
25k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
480
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Google's AI Overviews - The New Search
badams
0
1.1k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
How to make the Groovebox
asonas
2
2.3k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Building AI with AI
inesmontani
PRO
1
1.1k
Transcript
@stefanjudis I didn't know that!
My first job interview
“ We're running a Magento shop combined with a CouchDB
and a Frontend application with a Prototype/ jQuery mix.
“ We're running a Magento shop combined with a CouchDB
and a Frontend application with a Prototype/ jQuery mix.
“ We're running a Magento shop combined with a CouchDB
and a Frontend application with a Prototype/ jQuery mix.
“ We're running a Magento shop combined with a CouchDB
and a Frontend application with a Prototype/ jQuery mix. I didn't say that I didn't know most of these technologies...
... which lead to enormous stress.
8 years later
The dangerous knowledge comparison
What I think others know What I know
Web Development
None
None
You can't know everything!
“ Don’t Compare Your Behind-The-Scenes With Everyone's Highlight Reel. by
Tara Hunt
None
Know where to look for information
The learning journey won't end.
TIL: ... (Today I learned: ...)
None
But then I learned it's deprecated...
None
Twitter is neither a bookmarking nor documentation tool!
Write it down! Quick'n'dirty!
My learnings in 2 years (a random list in no
particular order) (not always useful)
NaNNaNNaN NaNNaN
parseInt('Hello world', 10)
parseInt('Hello world', 10) NaN
parseInt('Hello world', 10) NaN === NaN false
isNaN(NaN); // true
isNaN(NaN); // true isNaN(undefined); // true isNaN({}); // true isNaN(true);
// false isNaN(null); // false isNaN(37); // false
isNaN(NaN); // true isNaN(undefined); // true isNaN({}); // true isNaN(true);
// false isNaN(null); // false isNaN(37); // false function myIsNaN(value) { return value !== value; }
isNaN(NaN); // true isNaN(undefined); // true isNaN({}); // true isNaN(true);
// false isNaN(null); // false isNaN(37); // false myIsNaN(NaN); // true myIsNaN(undefined); // false myIsNaN({}); // false myIsNaN(true); // false myIsNaN(null); // false myIsNaN(37); // false
isNaN(NaN); // true isNaN(undefined); // true isNaN({}); // true isNaN(true);
// false isNaN(null); // false isNaN(37); // false myIsNaN(NaN); // true myIsNaN(undefined); // false myIsNaN({}); // false myIsNaN(true); // false myIsNaN(null); // false myIsNaN(37); // false Number.isNaN(NaN); // true Number.isNaN(undefined); // false Number.isNaN({}); // false Number.isNaN(true); // false Number.isNaN(null); // false Number.isNaN(37); // false
isNaN(NaN); // true isNaN(undefined); // true isNaN({}); // true isNaN(true);
// false isNaN(null); // false isNaN(37); // false myIsNaN(NaN); // true myIsNaN(undefined); // false myIsNaN({}); // false myIsNaN(true); // false myIsNaN(null); // false myIsNaN(37); // false Number.isNaN(NaN); // true Number.isNaN(undefined); // false Number.isNaN({}); // false Number.isNaN(true); // false Number.isNaN(null); // false Number.isNaN(37); // false Object.is(NaN, NaN); // true Object.is(undefined, NaN); // false Object.is({}, NaN); // false Object.is(true, NaN); // false Object.is(null, NaN); // false Object.is(37, NaN); // false
Object.is? === + SPECIAL HANDLING OF NaN, -0, +0
Object.is? Object.is(-0, 0); // false Object.is(NaN, NaN); // true SameValue
Comparison
['foo', 123, true, undefined, NaN].indexOf(NaN) ['foo', 123, true, undefined, NaN].includes(NaN)
true ['foo', 123, true, undefined, -0].includes(0) true SameValueZero Comparison -1
Abstract Equality Comparison Equality comparison and sameness == Strict Equality
Comparison ===, indexOf, ... SameValueZero includes, ... SameValue Object.is, ...
developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
Should I (force) push it?
$ history | grep amend 53 git co -p --amend
index.html 69 git co -p --amend 71 git co -p --amend content/blueprints 1538 git co -p --amend 1540 git co -p --amend migration-tests 1542 git co -p --amend migration-tests 1545 git co -p --amend test_app.py 1627 git co -p --amend 1842 git co --amend 1845 git co --amend 1941 git co --amend 2273 git co -p --amend ...
$ git co -p --amend index.html $ git push -f
origin some-feature
$ git co -p --amend index.html $ git push -f
origin some-feature It's very easy to overwrite remote changes with force pushing!
None
developer.atlassian.com/blog/2015/04/force-with-lease/
Process substitution
Process substitution $ bash <(curl -s https://codecov.io/bash)
“ Process substitution allows a process’s input or output to
be referred to using a filename.
$ echo <(ls .) /dev/fd/11
$ cat <(ls .) functions.sh .zshrc ...
$ node <(echo 'console.log("foo")') foo
$ node <(pbpaste) foo
$ node <(pbpaste) foo console.log("foo") But then I learned you
can pipe into Node.js
$ node <(pbpaste) foo
$ pbpaste | node foo
Break zooming with one line
None
body { font-size: 2vw; }
None
body { font-size: calc(1vw + 1em); }
None
Stylesheets do not only block rendering
<link rel="stylesheet" href="app.css" /> app.css START RENDER
<link rel="stylesheet" href="app.css" /> <script> var script = document.createElement('script'); script.src
= "analytics.js"; document.getElementsByTagName('head')[0].appendChild(script); </script>
<link rel="stylesheet" href="app.css" /> <script> var script = document.createElement('script'); script.src
= "analytics.js"; document.getElementsByTagName('head')[0].appendChild(script); </script> app.css analytics.js
<script> var script = document.createElement('script'); script.src = "analytics.js"; document.getElementsByTagName('head')[0].appendChild(script); </script>
<link rel="stylesheet" href="app.css" /> app.css analytics.js
WAT!!!
None
{ 'ü': 'foo', 'ü': 'bar', '': 'baz', '': 'wat!' }
{ 'ü': 'foo', 'u\u0308': 'bar', '': 'baz', '': 'wat!' }
{ 'ü': 'foo', 'u\u0308': 'bar', '': 'baz', '\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66': 'wat!' }
“ Two IdentifierName that are canonically equivalent according to the
Unicode standard are not equal unless they are represented by the exact same sequence of code units.
“ Two IdentifierName that are canonically equivalent according to the
Unicode standard are not equal unless they are represented by the exact same sequence of code units.
Unicode is powerful and very fascinating (and scary)
https://www.fileformat.info/info/unicode/char/202e/index.htm
None
"Logical" string comparisons
'aBcD' === 'abcd'
'aBcD' === 'abcd' // false
'aBcD' === 'abcd' // false 'ábcd' === 'abcd'
'aBcD' === 'abcd' // false 'ábcd' === 'abcd' // false
'aBcD' === 'abcd' // false 'ábcd' === 'abcd' // false
'Price 2€' > 'Price 1€'
'aBcD' === 'abcd' // false 'ábcd' === 'abcd' // false
'Price 2€' > 'Price 1€' // true
'aBcD' === 'abcd' // false 'ábcd' === 'abcd' // false
'Price 2€' > 'Price 1€' // true 'Price 20€' > 'Price 3€'
'aBcD' === 'abcd' // false 'ábcd' === 'abcd' // false
'Price 2€' > 'Price 1€' // true 'Price 20€' > 'Price 3€' // false
localCompare 'aBcD'.localeCompare('abcd', undefined, { sensitivity: 'base' }) // 0 'ábcd'.localeCompare('abcd',
undefined, { sensitivity: 'base' }) // 0
localCompare a ≠ b, a = á, a = A
'aBcD'.localeCompare('abcd', undefined, { sensitivity: 'base' }) // 0 'ábcd'.localeCompare('abcd', undefined, { sensitivity: 'base' }) // 0
localCompare 'Price 2€'.localeCompare('Price 3€', undefined, { numeric: true }) //
-1 'Price 3€'.localeCompare('Price 3€', undefined, { numeric: true }) // 0 'Price 23€'.localeCompare('Price 3€', undefined, { numeric: true }) // 1
localCompare 'Price 2€'.localeCompare('Price 3€', undefined, { numeric: true }) //
-1 'Price 3€'.localeCompare('Price 3€', undefined, { numeric: true }) // 0 'Price 23€'.localeCompare('Price 3€', undefined, { numeric: true }) // 1 "1" < "2" < "10"
How to center elements
None
.center { display: flex; align-items: center; justify-content: center; }
.center { display: flex; align-items: center; justify-content: center; } .center-using-grid
{ display: grid; align-items: center; justify-items: center; }
.center { display: flex; align-items: center; justify-content: center; } .center-using-grid
{ display: grid; place-items: center; }
.center { display: flex; align-items: center; justify-content: center; } .center-using-grid
{ display: grid; place-items: center; } 2 declarations!
None
developer.mozilla.org/en-US/docs/Web/CSS/place-items place-items support
Querying the DOM is not equal querying the DOM
<ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul> document.querySelectorAll('li'); // NodeList(3) [li, li,
li]
<ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul> document.querySelectorAll('li'); // NodeList(3) [li, li,
li] document.getElementsByTagName('li'); // HTMLCollection(3) [li, li, li]
<ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul> NodeList(3) HTMLCollection(3)
<ul> <li>foo</li> <li>bar</li> <li>baz</li> <li>wat</li> </ul> NodeList(3) HTMLCollection(4)
<ul> <li>foo</li> <li>bar</li> <li>baz</li> <li>wat</li> </ul> NodeList(3) HTMLCollection(4) There are
live and static element collections
document.querySelectorAll // static NodeList
document.querySelectorAll // static NodeList element.childNodes // live NodeList
document.querySelectorAll // static NodeList element.childNodes // live NodeList element.children //
(live) HTMLCollection
document.querySelectorAll // static NodeList element.childNodes // live NodeList element.children //
(live) HTMLCollection document.getElementsByTagName // (live) HTMLCollection
www.stefanjudis.com/blog/accessing-the-dom-is-not-equal-accessing-the-dom
WAT!!! (part 2)
<label for="foo">Fooo</label> <p>Some more information</p> <input id="foo"> #foo:hover { background:
DeepSkyBlue; }
None
“ Document languages may define additional ways in which an
element can match :hover. For example, [HTML5] defines a labeled control element as matching :hover when its label is hovered.
“ Document languages may define additional ways in which an
element can match :hover. For example, [HTML5] defines a labeled control element as matching :hover when its label is hovered.
kizu.ru/en/blog/label-to-input/
Regular expressions
const regex = /Jane.Smith/; regex.test('Jane Smith'); // true regex.test('Jane\nSmith'); //
false
const regex = /Jane.Smith/; regex.test('Jane Smith'); // true regex.test('Jane\nSmith'); //
false '.' doesn't actually match all characters!
const regex = /Jane.Smith/; regex.test('Jane Smith'); // true regex.test('Jane\nSmith'); //
false
const regex = /Jane.Smith/s; regex.test('Jane Smith'); // true regex.test('Jane\nSmith'); //
true
github.com/tc39/proposal-regexp-dotall-flag
* * use with Babel dotall flag support * *
const regex = /Jane.Smith/;
const regex = /(Jane|John).(Smith|Miller)/; 'John Smith'.match(regex); // [ "John Smith",
"John", "Smith" ]
const regex = /(Jane|John).(Smith|Miller)/; 'John Smith'.match(regex); // [ "John Smith",
"John", "Smith" ]
const regex = /(?:Jane|John).(Smith|Miller)/; 'John Smith'.match(regex); // [ "John Smith","Smith"
]
const regex = /(?:Jane|John).(Smith|Miller)/; 'John Smith'.match(regex); // [ "John Smith","Smith"
] There are non-capturing groups in JavaScript
Why we won't have element queries
Why we (probably) won't have element queries
None
.mod img { display: block; margin: 0 auto; width: 100%;
max-width: 250px; }
.mod img { display: block; margin: 0 auto; width: 100%;
max-width: 250px; } .mod:media( min-width: 425px ) img { float: left; width: 30%; max-width: 9999px; }
None
.box { width: 1200px; }
.box { width: 1200px; }
.box { width: 1200px; } .box:media(min-width: 1200px) { width: 1000px;
}
.box { width: 1200px; } .box:media(min-width: 1200px) { width: 1000px;
}
.box { width: 1200px; } .box:media(min-width: 1200px) { width: 1000px;
}
.box { width: 1200px; } .box:media(min-width: 1200px) { width: 1000px;
}
.box { width: 1200px; } .box:media(min-width: 1200px) { width: 1000px;
}
.box { width: 1200px; } .box:media(min-width: 1200px) { width: 1000px;
} And now, we're in a loop...
https://css-tricks.com/selectors-that-depend-on-layout/
Checking for an existing class
<div class="component"></div>
<div class="component is-active"></div>
const elem = querySelector('.component'); if( elem.classList.contains('is-active') && elem.classList.contains('is-awesome') ) {
/* ... */ } <div class="component is-active is-awesome"></div>
const elem = querySelector('.component'); if( elem.matches('.is-active') && elem.matches('.is-awesome') ) {
/* ... */ } <div class="component is-active is-awesome"></div>
const elem = querySelector('.component'); if(elem.matches('.is-active.is-awesome')) { /* ... */ }
<div class="component is-active is-awesome"></div>
“ The Element.matches() method returns true if the element would
be selected by the specified selector string; otherwise, returns false.
“ The Element.matches() method returns true if the element would
be selected by the specified selector string; otherwise, returns false.
background-repeat has other options than repeat
.box { }
.box { background-image: url(https://.../jsunconf.svg); }
.box { background-image: url(https://.../jsunconf.svg); background-repeat: repeat; }
.box { background-image: url(https://.../jsunconf.svg); background-repeat: round; }
.box { background-image: url(https://.../jsunconf.svg); background-repeat: space; }
min-content/ max-content
Merel van der Woude Creative director bij Butterfly Works
Merel van der Woude Creative director
Merel van der Woude Creative director, overall great person, loves
books
Merel van der Woude Creative director, overall great person, loves
books
Merel van der Woude Creative director, overall great person, loves
books That's not possible, is it?
<h2> Merel van der Woude <span>Creative director</span> </h2>
<h2> Merel van der Woude <span>Creative director</span> </h2> h2 {
width: min-content; min-width: 0; max-width: 100%; }
<h2> Merel van der Woude <span>Creative director</span> </h2> h2 {
width: min-content; min-width: 0; max-width: 100%; } h2 span { width: max-content; max-width: 100%; }
https://codepen.io/maddesigns/pen/YNXvMz
Dry package configuration
{ "name": "my-package", "scripts": { "lint": "eslint ./src/*", "test": "jest
./src/*" } }
{ "name": "my-package", "config": { "src": "./src/*" }, "scripts": {
"lint": "eslint $npm_package_config_src", "test": "jest $npm_package_config_src" } }
{ "name": "my-package", "config": { "src": "./src/*" }, "scripts": {
"lint": "eslint $npm_package_config_src", "test": "jest $npm_package_config_src" } } Avoid duplication
{ "foo": "bar" "scripts": { "start": "node index.js" } }
{ "foo": "bar" "scripts": { "start": "node index.js" } }
// index.js console.log(process.env.npm_package_foo); // 'bar'
And finally...
function f() { try { return 'A'; } finally {
return 'B'; } } f(); // ? 'B'
function g() { try { throw new Error('Foo'); } catch(
e ) { return 'A'; } finally { return 'B'; } } f(); // ? 'B'
function h() { try { throw new Error('Foo'); } finally
{ return 'B'; } } h(); //? 'B' (without throwing exception)
function i() { try { throw new Error('Foo'); } catch(
e ) { throw new Error('Bar'); return 'A'; } finally { return 'B'; } } i(); //? 'B' (without throwing exception)
“ If the finally block returns a value, this value
becomes the return value of the entire try-catch-finally production, regardless of any return statements in the try and catch blocks.
“ If the finally block returns a value, this value
becomes the return value of the entire try-catch-finally production, regardless of any return statements in the try and catch blocks.
77 documented learnings
www.stefanjudis.com/today-i-learned
It only takes 10 minutes
None
Did I improve? Like, at all? Oh yes!!!
I'm building my own knowledge base!
Celebrate learnings!
Huh! I didn't know that!
THANKS FOR LISTENING! @stefanjudis www.stefanjudis.com my-links.online/i-didnt-know
THANKS FOR LISTENING! @stefanjudis www.stefanjudis.com my-links.online/i-didnt-know Yes, I bought my-links.online
THANKS FOR LISTENING! @stefanjudis www.stefanjudis.com my-links.online/i-didnt-know