TIL - Today I learned

  • String.prototype.normalize for safer string comparison

    Today I came a across the String.prototype.normalize function which I haven't used before. It exists to make string comparisons more reliable.

    Let's me show you a quick example:

    // pick a random word with a German Umlaut
    const word = 'über';         // displayed as 'über'
    console.log( word.length );  // 4
    
    const alikeWord = 'u\u0308ber';  // displayed as 'über'
    console.log( alikeWord.length ); // 5
    
    console.log( word === alikeWord ); // false

    As you see strings that look completely identical to us doesn't have to be the same internally. The string alikeWord makes use of a Combining Diacritical Mark to generate the German Umlaut ü – to be specific it uses COMBINING DIAERESIS. The thing is that ü also has its own codepoint in Unicode. Now we have two ways to display this glyph which makes comparison a bit tricky.

    To solve this issue we can use normalize to well... yeah normalize strings. ;)

    const word = 'über';         // displayed as 'über'
    console.log( word.length );  // 4
    
    const alikeWord = 'u\u0308ber'.normalize(); // displayed as 'über'
    console.log( alikeWord.length );            // 4
    
    console.log( word === alikeWord ); // true
  • How to quick save links to Google Inbox

    This might not a big deal for some people but for me this saves a lot of time. My usual flow is to "bookmark" read later links in Google Inbox. The way I did this so far was to copy a link manually, switch to Inbox and save it there. Addy Osmani told me today that I can do this easily with the share option! 🎉

  • Conditional properties with object spread

    Kris Urbas shared a really neat trick to deal with conditional object properties using the object spread operator (currently at proposal stage 3).

    const shouldAddProp2 = false;
    const obj = {
      prop1: 2,
      ...shouldAddProp2 && { conditionalProp2: 2 }
    }
    
    // it's like
    // Object.assign( obj, ( shouldAddProp2 && { conditionalProp2 : 2 } ) );
    
    console.log( obj );

    Today this snippet is still hard to read for me, so I have to figure out if I should use this in the future, but it's a neat trick for sure. You can play around with it in the Babel repl.

  • A use case for CSS min-content and max-content

    Recently I came across the CSS width property values min-content and max-content. I haven't heard of these before and couldn't imagine when these values would be useful. So I asked Twitter to get some answers. As usual Sven Wolfermann helped me out and sent me a CodePen which showed when I'd want to use these values.

    min-content max-content use case

    As you see in the CodePen example the subline is controlling the overall width of the headline. If you would have asked me a month ago I'd probably would have said that this is not possible in CSS.

    See the Pen CSS Question by @vasilis – min/max-content by Sven Wolfermann (@maddesigns) on CodePen.

    I never had to build a layout like this, but good to know that it's possible. ;)

  • Powerful history command shortcuts in bash

    Ashley Williams tweeted that !! in commit messages will be replaced with the last executed command.

    It turns out this is nothing git specific but rather command line specific and there are a lot more:

    • !! - last command
    • !1 - first entry in history
    • !-1 - last entry in history
    • !ssh - last command starting with ssh
    • !:1 - first argument of last command

    For the case of git this works only when using -m though. ;) If you want to read more about this Digital Ocean published a nice article on this topic.

  • Completion values in JavaScript

    Paul Irish tweeted a while back a code snippet that puzzled him (and me).

    > "omg"; var x = 4;
    // "omg"
    
    > eval( `"omg"; var x = 4;` );
    // "omg"

    We both expected that the "return value" of this lines will be undefined. It turns out what we see after evaluating these lines in a JavaScript console are not return values but rather a statement completion values. If you want to dig deeper in this topic Matt Zeunert enlightened me with his article.

  • var let = 12 is valid JavaScript

    Yoshua Wuyts tweeted that var let = 12 is valid JavaScript. Wat? It turns out let is no reserved word in JavaScript. If you want to dig deeper there is an interesting read on this topic, that was recently released on the Bocoup blog. ;)

    Edited: Turns out this is only true in sloppy mode. Thanks Robin!

  • You can import Google Analytics Stats in caniuse.com

    Heydon Pickering shared a tweet mentioning that you can import Google Analytics stats in caniuse.com! Woah! 🎉

  • Double-click the edges of a window in macOS to expand it

    I came across this tweet by Jason Miller which shows a feature of macOS I didn't know about. You can expand any window by double clicking its edges.

  • console.dir() is short for console.log( util.inspect() )

    Sometimes when debugging node scripts via console.log you'll run into the situation, that console.log won't show you the complete object you want to inspect.

    console.log( { foo: { bar: { baz: { foo: 'Show me!' } } } } );
    // { foo: { bar: { baz: [Object] } } }

    The solution to this problem is to use util.inspect which also includes the option to color the output.

    console.log( util.inspect( { foo: { bar: { baz: { foo: 'Show me!' } } } }, { depth: null, colors: true } );
    // { foo: { bar: { baz: { foo: 'Show me!' } } } }

    Frederic Hemberger just told me that console.dir uses util.inspect under the hood, which means we can make it even shorter! 🎉

    console.dir( { foo: { bar: { baz: { foo: 'Show me!' } } } }, { depth: null, colors: true } );
    // { foo: { bar: { baz: { foo: 'Show me!' } } } }
  • Useful background-repeat options other than repeat

    Kudos to Chris Coyier who posted an article on background-repeat. I didn't know about the properties space and round. 🎉

    See the Pen The Different background-repeats by Chris Coyier (@chriscoyier) on CodePen.

  • finally in a try/catch statements really goes over everything

    Today I woke up checked Slack and saw a little trick question by my friend Tomasz in one of the JavaScript channels.

    function f() {
      try {
        return 'A';
      } finally {
        return 'B';
      }
    }
    
    f(); // ?

    I don't use the finally block in try/catch statements very often so I was not sure what the return value will be for this snippet. It turns out the finally block goes over everything according to MDN:

    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.

    So let's have a look at a few examples:

    function f() {
      try {
        return 'A';
      } finally {
        return 'B';
      }
    }
    
    f(); // 'B'
    
    // ***********************************************
    
    function g() {
      try {
        throw new Error( 'Foo' );
      } catch( e ) {
        return 'A';
      } finally {
        return 'B';
      }
    }
    
    g(); // 'B'
    
    // ***********************************************
    
    function h() {
      try {
        throw new Error( 'Foo' );
      } finally {
        return 'B';
      }
    }
    
    h(); // 'B' (without throwing an exception)
    
    // ***********************************************
    
    function i() {
      try {
        throw new Error( 'Foo' );
      } catch( e ) {
        throw new Error( 'Bar' );
        return 'A';
      } finally {
        return 'B';
      }
    }
    
    i(); // 'B' (without throwing an exception)

    finally overwrites return statements and also "catches" exceptions. Good to know. ;)

  • Skipped holes in JavaScript Arrays

    Today I came along a code example that used the delete operator to remove an element from an array. This is an operation that is rarely useful IMO because it creates holes in an array.

    let foo = [ 1, 2, 3, 4 ];
    
    delete foo[ 1 ];
    delete foo[ 2 ];
    
    console.log( foo );
    // logs in Chrome '[1, 3: 4]'
    
    console.log( foo.length );
    // logs in Chrome '4'
    
    console.log( foo.toString() );
    // logs in Chrome '1,,,4'

    I think everybody should avoid holes in arrays, but I kept reading about it out of curiosity and discovered that array methods like forEach skip holes in arrays. I didn't know that. This makes sense, but bugs caused by this can takes ages to be found.

    let foo = [ 1, 2, 3, 4 ];
    delete foo[ 1 ];
    
    foo.forEach( ( value, index ) => console.log( index, value ) );
    // 0 1
    // 2 3
    // 3 4

    At the end I'll still avoid the usage of the delete operator for arrays to not create holes, but I think it's good to know about these things...

    If you want to read more about this topic I highly recommend you to check out Axel Rauschmayers's section about holes in JavaScript arrays in "Speaking JavaScript".

  • U+202E - RIGHT-TO-LEFT OVERRIDE

    Thanks to a tweet by @FakeUnicode I came across the unicode character U+202E today. This character changes all subsequent text to be right-to-left. In short – this invisible character leads to not understandable behavior in any environment. A quick Google search also revealed that this character is used to disguise malicious files.

    You can use it in HTML (‮), in JavaScript strings (\u202E) and it's also working in Google Docs. :D

    202e-unicode

  • Interfere Constructor calls with ES6 Proxies

    I came along ES6 Proxies and asked myself how to interfere a new call. Here we go!

    // proxy handler
    const handler = {
      // let's interfere the `new` call
      // log out which object was called with which arguments
      construct : ( target, args ) => {
        console.log( `Initializing ${ target.name } with:`, args );
        return new target();
      }
    };
    
    /**
     * Interfere a constructor function
     */
    function ConstructorFunction() {
      this.call = () => {
        console.log( 'method call 1' );
      };
    }
    
    const ProxiedConstructorFn = new Proxy( ConstructorFunction, handler );
    const foo = new ProxiedConstructorFn( 'foo' );
    // logs "Initializing ConstructorFunction", [ "foo" ]
    foo.call();
    // logs "method call 1"
    
    /**
     * Interfere a class constructor
     */
    class ClassConstruct {
      constructor() {}
    
      call() {
        console.log( 'method call 2' );
      }
    }
    
    const ProxiedClass = new Proxy( ClassConstruct, handler );
    const bar = new ProxiedClass( 'bar' );
    // logs "Initializing ClassConstruct", [ "bar" ]
    bar.call();
    // logs "method call 2"

    It's not only get, set and new that can be interfered. You can find a complete list on MDN.

  • Time based git logging

    You can log entries in a specific timeframe. Perfect to check commits for the daily stand up.

    $ git log --since="yesterday"
    $ git log --since="last month"