├── .gitignore ├── test ├── index.html ├── index.js ├── object-literals.js ├── arrow-functions.js └── multiline.js ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('./arrow-functions'); 2 | require('./object-literals'); 3 | require('./multiline'); -------------------------------------------------------------------------------- /test/object-literals.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | 3 | test('literal', function(t){ 4 | t.plan(1); 5 | 6 | function foo(){} 7 | 8 | var x = {foo}; 9 | 10 | t.deepEqual(x, {foo: foo}); 11 | }); 12 | 13 | test('literal get', function(t){ 14 | t.plan(1); 15 | 16 | function get(){} 17 | 18 | var x = {get}; // throws in node v4/5 19 | 20 | t.deepEqual(x, {get: get}); 21 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es-twentysixnext", 3 | "version": "1.0.0", 4 | "description": "Warning: contains both facts and opinions about es-whateverthefuck.", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "node --harmony test", 11 | "watch": "watchify test/index.js -o test/index.browser.js -d" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/KoryNunn/es-twentysixnext.git" 16 | }, 17 | "author": "", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/KoryNunn/es-twentysixnext/issues" 21 | }, 22 | "homepage": "https://github.com/KoryNunn/es-twentysixnext#readme", 23 | "devDependencies": { 24 | "tape": "^4.2.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/arrow-functions.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | 3 | test('arrow function', function(t){ 4 | t.plan(1); 5 | 6 | var foo = x => x+5; 7 | 8 | t.equal(foo(1), 6); 9 | }); 10 | 11 | test('arrow function with object-literal', function(t){ 12 | t.plan(1); 13 | 14 | /* 15 | Fails because it parses the curlys as the fn body.. 16 | */ 17 | 18 | var x = 10, 19 | foo = x => {x}, 20 | expected = {x}; 21 | 22 | t.notDeepEqual(foo(x), expected); 23 | }); 24 | 25 | test('arrow function with object-literal and curley body', function(t){ 26 | t.plan(1); 27 | 28 | /* 29 | Still fails because when you use curlys you lose implicit return. 30 | */ 31 | 32 | var x = 10, 33 | foo = x => {{x}}, 34 | expected = {x}; 35 | 36 | t.notDeepEqual(foo(x), expected); 37 | }); 38 | 39 | test('arrow function with object-literal and curley body and return', function(t){ 40 | t.plan(1); 41 | 42 | var x = 10, 43 | foo = x => {return {x}}, 44 | expected = {x}; 45 | 46 | t.deepEqual(foo(x), expected); 47 | }); -------------------------------------------------------------------------------- /test/multiline.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | 3 | test('multiline spacing with nice formatting', function(t){ 4 | t.plan(1); 5 | 6 | var multilineString = 7 | `Hello 8 | world, Isn't this just the best? 9 | 10 | I can see why this is a useful feature..` 11 | 12 | 13 | var normalString = [ 14 | "Hello", 15 | "world, Isn't this just the best?", 16 | "", 17 | "I can see why this is a useful feature.." 18 | ].join('\n'); 19 | 20 | t.notEqual(multilineString, normalString); 21 | 22 | }); 23 | 24 | 25 | test('multiline spacing with terrible formatting', function(t){ 26 | t.plan(1); 27 | 28 | var multilineString = 29 | `Hello 30 | world, Isn't this just the best? 31 | 32 | I can see why this is a useful feature..` 33 | 34 | 35 | var normalString = [ 36 | "Hello", 37 | "world, Isn't this just the best?", 38 | "", 39 | "I can see why this is a useful feature.." 40 | ].join('\n'); 41 | 42 | t.equal(multilineString, normalString); 43 | 44 | }); 45 | 46 | var template = (string, scope) => string.replace(/\$\{(.+?)\}/g, (match, key) => scope[key]); 47 | 48 | test('multiline cant even template', function(t){ 49 | t.plan(1); 50 | 51 | var notRealyATemplate = `Hello ${world}`, 52 | aTemplate = "Hello ${world}"; 53 | 54 | var world = 'World'; 55 | 56 | var expected = template(aTemplate, {world}); 57 | 58 | var actual = notRealyATemplate; // uhh.. screwed! Can't template, because it's already resolved! 59 | 60 | t.notEqual(actual, expected); 61 | 62 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # es-twentynextsixbabel 2 | 3 | Warning: contains both facts and opinions about es-whateverthefuck. 4 | 5 | Many things taken from here: https://github.com/lukehoban/es6features 6 | 7 | **My opinions are subject to pull requests.** 8 | 9 | # arrows 10 | 11 | ## What 12 | 13 | Shorthand functions, implicit returns^ 14 | 15 | ``` 16 | [1, 2, 3].map(x => x * 2) // -> [2, 4, 6] 17 | ``` 18 | 19 | Also doesn't bind scope... 20 | 21 | ## Why 22 | 23 | People don't like hitting lots of keys. 24 | People don't like thinking about `this` 25 | 26 | ## The good 27 | 28 | Great for little throw-away-style expressions. 29 | Great in functional style code eg: 30 | 31 | ``` 32 | var names = arrayOfPeople.map(person => person.name); 33 | ``` 34 | 35 | ## The bad. 36 | 37 | There are many forms: 38 | 39 | No braces: 40 | ``` 41 | x => x + 1 42 | ``` 43 | 44 | some braces: 45 | ``` 46 | (x, y) => x + y 47 | ``` 48 | 49 | some other braces: 50 | ``` 51 | x => { x+= 20; return x.toString(); } 52 | ``` 53 | 54 | tuns-o-braces: 55 | ``` 56 | (x, y) => { x += y; return x.toString(); } 57 | ``` 58 | 59 | ## The Ugly 60 | 61 | ### So many versions 62 | 63 | ^: Implicit returns, unless you use curly braces, obviously. 64 | ``` 65 | var doThing1 = x => x; 66 | 67 | doThing1(10); // -> 10 68 | 69 | var doThing2 = x => {x}; 70 | 71 | doThing2(10); // -> undefined 72 | 73 | var doThing3 = (x) => {x}; 74 | 75 | doThing3(10); // -> undefined 76 | 77 | var doThing4 = (x) => x; 78 | 79 | doThing4(10); // -> 10 80 | 81 | var doThing5 = (x) => {return x}; 82 | 83 | doThing5(10); // -> 10 84 | 85 | var doThing5 = x => return x; // -> Uncaught SyntaxError: Unexpected token return 86 | ``` 87 | 88 | ### Plays well with other es-sinex15 features 89 | 90 | Say I have a value, and I want to turn that into an object like so: 91 | ``` 92 | { 93 | x: x 94 | } 95 | ``` 96 | 97 | You can do this in es-sinex15 like so: 98 | 99 | ``` 100 | {x} // -> {x: x} 101 | ``` 102 | 103 | Cool! let's throw in some arrow functions: 104 | 105 | ``` 106 | [1, 2, 3].map(x => {x}) // -> [undefined, undefined, undefined] 107 | ``` 108 | 109 | Awesome. Wrap it in another layer of braces then.. 110 | 111 | ``` 112 | [1, 2, 3].map(x => {{x}}) // -> [undefined, undefined, undefined] 113 | ``` 114 | 115 | Oh right, no implicit returns anymore.. 116 | 117 | ``` 118 | [1, 2, 3].map(x => {return {x}}) // -> [{x: 1}, {x: 2}, {x: 3}] 119 | ``` 120 | 121 | Nice.. 122 | 123 | Of course you can use parentheses to get the result we want: 124 | 125 | ``` 126 | [1, 2, 3].map(x => ({x})) // -> [{x: 1}, {x: 2}, {x: 3}] 127 | ``` 128 | 129 | # classes 130 | 131 | I can't. No. Just don't. 132 | 133 | # enhanced object literals 134 | 135 | ## What 136 | 137 | Allows you to construct objects a bit nicer: 138 | 139 | ``` 140 | var x = 10; 141 | 142 | var obj = {x}; 143 | 144 | obj // -> {x: 10}; 145 | ``` 146 | 147 | Also now supports computed properties: 148 | 149 | ``` 150 | var value = 'World', 151 | obj = { 152 | ['hello' + value]: value 153 | }; 154 | 155 | obj // -> {helloWorld: 'World'} 156 | ``` 157 | 158 | ## The good 159 | 160 | Being able to make objects without repeating yourself is quite handy, 161 | and being able to create computed properties without using `[someKey]` is pretty good too. 162 | 163 | ``` 164 | function createPerson(firstName, surname, age){ 165 | return {firstName, surname, age}; 166 | } 167 | ``` 168 | 169 | ## The Bad 170 | 171 | Functionally, there is nothing bad about these features 172 | 173 | ~~Nevermind, of cource there are problems.~~ 174 | 175 | ``` 176 | var x = {y} //legit 177 | var x = {get} // fucked 178 | ``` 179 | 180 | ~~Because `get` is a magic property used for getter/setters..~~ 181 | 182 | NEVERMIND AGAIN! That was just a v8 bug which is now fixed. 183 | 184 | ## The ugly 185 | 186 | WHY DID THEY USE SQUARE BRACES FOR COMPUTED PROPERTIES!? 187 | 188 | If only there was an existing way to say 'Do this first', OH WAIT! 189 | 190 | ``` 191 | // Calculate 5 + 6 first. 192 | var x = (5 + 6) * 10; 193 | ``` 194 | 195 | Wouldn't that have been nicer? 196 | 197 | ``` 198 | { 199 | // CALCULATE THIS: THEN ASSIGN THIS! 200 | ('hello' + value): value 201 | } 202 | ``` 203 | 204 | Also literals get a little confusing when you mix'n'match: 205 | 206 | ``` 207 | {x: 'majigger', y, z} 208 | ``` 209 | 210 | # template strings 211 | 212 | ## What 213 | 214 | Exactly what you'd expect. Template values into a string. 215 | 216 | Oh but also just jam multiline support together with it because. 217 | 218 | 219 | ``` 220 | var myString = `Hello world, 221 | Hey look multiline! Also, lets pull ${anything} from scope`; 222 | 223 | ``` 224 | 225 | ## The good 226 | 227 | Umm.. I guess multiline is cool? oh but wait.. 228 | 229 | ## The bad 230 | 231 | Why do template strings even exist? 232 | Let's write a function that implements template strings, 233 | with the added bonus of the string not pulling random crap from scope: 234 | 235 | ``` 236 | var template = (string, scope) => string.replace(/\$\{(.+?)\}/g, (match, key) => scope[key]); 237 | 238 | var world = 'planet'; 239 | 240 | template('Hello ${world}', {world}) // -> 'Hello planet' 241 | ``` 242 | 243 | Wow I can see why that's a language feature.. 244 | 245 | Also, you can't put the template in a variable and use it later, since it immediately evaluates. 246 | 247 | Also, using your own function means that you can decide what your token syntax is. 248 | 249 | ## The ugly 250 | 251 | How do you do multiline when you're in a non-whitespace-sensitive language? Badly! :D 252 | 253 | ``` 254 | var greeting = `Hello! 255 | How are you today?` 256 | 257 | greeting // -> "Hello!\n How are you today?" 258 | ``` 259 | 260 | Yeah so if you're in a block, just mess everything up: 261 | 262 | ``` 263 | function foo(){ 264 | 265 | function bar(){ 266 | return `my 267 | cool 268 | multi 269 | line 270 | string`; 271 | } 272 | 273 | } 274 | ``` 275 | 276 | Nice........... 277 | 278 | # destructuring 279 | 280 | Assign values to variables out of objects using pattern matching. 281 | 282 | ``` 283 | function distance(point1, point2){ 284 | var [x1, y1] = point1, 285 | [x2, y2] = point2; 286 | 287 | return Math.sqrt( 288 | Math.pow(x1 - x2, 2) + 289 | Math.pow(y1 - y2, 2) 290 | ); 291 | } 292 | 293 | distance([10, 10], [20, 20]); 294 | // -> 14.142135623730951 295 | ``` 296 | 297 | ## The good 298 | 299 | Everything. This is a good feature. 300 | 301 | ## The Bad 302 | 303 | Can't see any issues 304 | 305 | ## The ugly 306 | 307 | Its power may lead to mess, since you can do deep matching (which is also cool) 308 | 309 | ``` 310 | var {foo: {bar: {baz: {x: x}}}} = obj; 311 | ``` 312 | 313 | # default + rest + spread 314 | 315 | ## What 316 | 317 | Defaults: 318 | 319 | ``` 320 | function foo(x=10){ 321 | return x; 322 | } 323 | 324 | foo(5) // -> 5 325 | foo() // -> 10 326 | ``` 327 | 328 | Rest: 329 | 330 | ``` 331 | function foo(a, b, c...){ 332 | return a + b + c.join(' '); 333 | } 334 | 335 | foo('a', 'b', 'c', 'd', 'e', 'f') // -> 'abcdef' 336 | ``` 337 | 338 | Spread: 339 | 340 | ``` 341 | function add(a, b){ 342 | return a + b; 343 | } 344 | 345 | add(1, 2) // -> 3 346 | 347 | var values = [3, 4]; 348 | add(...values) // -> 7 349 | ``` 350 | 351 | ## The good 352 | 353 | Again, this stuff is excelent. These are features that you can't trivially implement with plain javascript. 354 | 355 | ## The ugly 356 | 357 | Defaults accept destructuring assignment. This is a HORRIBLE HORRIBLE feature! 358 | 359 | Via @yoshuawuyts 360 | ``` 361 | var fn = ({foo = 3, bar = 4} = {}) => {}; 362 | ``` 363 | 364 | READABILITY--! 365 | 366 | # let + const 367 | 368 | UUuuuuguhhh. 369 | 370 | `let`: block scoped `var` 371 | 372 | `const` `let` but you can't assing to it twice. 373 | 374 | ## The good 375 | 376 | Um.. I guess if you aren't used to lexical scoping..? 377 | 378 | ## The bad 379 | 380 | let is just var but block-scoped. Rather than spending 20s to learn how JS works, let's add syntax. 381 | 382 | ## The ugly 383 | 384 | ~~Attempting to assign a value to a const after declaration silently fails, 385 | but returns the value you attempted to assign.~~ 386 | 387 | ``` 388 | const x = 10; // -> 10 389 | 390 | x = 20; // -> 20 391 | 392 | x; // -> 10 393 | ``` 394 | 395 | UPDATE: FIXED! latest browsers and node now throw. 396 | 397 | 398 | ~~Declairing a const without immediately assigning a value results in `undefined` as expected, 399 | which is effectivly totally pointless.~~ 400 | 401 | ``` 402 | const x; -> undefined, forever. Pointless. 403 | ``` 404 | 405 | UPDATE: FIXED! latest browsers and node now throw. 406 | 407 | # iterators + for..of 408 | 409 | ## What 410 | Allows for custom implementation of iterators. 411 | 412 | I haven't looked too far into these, but they look ok so far. 413 | 414 | # The good, bad, ugly 415 | 416 | Sorry, I'm lazy, you'll have to find out for yourself :) 417 | 418 | # generators 419 | 420 | ## What 421 | 422 | Used in languages that don't have first-class functions to return a different value each time the function is called. 423 | 424 | ## The good 425 | 426 | ??? 427 | 428 | ## The bad 429 | 430 | This is just pointless sugar. You can implement the functionality of generators trivially in ES3. 431 | 432 | Stolen directly from https://github.com/lukehoban/es6features 433 | 434 | Fibonacci with generators: 435 | 436 | ``` 437 | var fibonacci = { 438 | [Symbol.iterator]: function*() { 439 | var pre = 0, cur = 1; 440 | for (;;) { 441 | var temp = pre; 442 | pre = cur; 443 | cur += temp; 444 | yield cur; 445 | } 446 | } 447 | } 448 | ``` 449 | 450 | The same shit without generators: 451 | 452 | ``` 453 | var fibonacci = function(){ 454 | [Symbol.iterator]() { 455 | let pre = 0, cur = 1; 456 | return { 457 | next() { 458 | [pre, cur] = [cur, pre + cur]; 459 | return { done: false, value: cur } 460 | } 461 | } 462 | } 463 | } 464 | ``` 465 | 466 | Same length, same functionality, why bother. 467 | 468 | ## The ugly 469 | 470 | They exist. 471 | 472 | # unicode 473 | 474 | There is new unicode support. Seems fine, I'm lazy, ¯\\_(ツ)_/¯ 475 | 476 | # modules 477 | 478 | ## What 479 | 480 | Like `require()` but hard-baked into the language, and using `import` and `export` instead. 481 | 482 | someModule.js 483 | ``` 484 | export function foo(){ 485 | return 'bar'; 486 | } 487 | ``` 488 | 489 | anotherModule.js 490 | ``` 491 | import foo from 'someModule.js'; 492 | 493 | foo() // -> 'bar'; 494 | ``` 495 | 496 | ## The good 497 | 498 | ??? 499 | 500 | ## The bad 501 | 502 | It's the same as require but with quirks. You can do all the destructiong with, supprise, destructuring. 503 | 504 | ## The ugly 505 | 506 | Nothing super bad that I know of. 507 | 508 | # module loaders 509 | 510 | Kinda ties in with the above stuff, allows you to screw with the module cache. 511 | I'm going to ¯\\_(ツ)_/¯ this one too. 512 | 513 | # map + set + weakmap + weakset 514 | 515 | ## What 516 | 517 | Map: `key: value` where `key` can be any value at all, including objects/functions. 518 | Set: Distinct list of any value. Can be itterated over. 519 | WeakMap: `key: value` where `key` must be an instance of an object (or function). References are weakly held. 520 | WeakSet: Distinct list of references. Cannot be itterated over, only checked if it contains a value. 521 | 522 | Too much to go into in this talk. 523 | 524 | ## The good 525 | 526 | These are great additions to JS, they cannot be implemented in ES3, and are non-trivial to implement in ES5, and polyfills are slow. 527 | 528 | Weak(map/set) are especially excelent, and open up a whole range of options that were previously impossible/impractical. 529 | 530 | ## The bad 531 | 532 | Nothing really, safari doesn't implement iterators correctly? Not really a fault of the spec. 533 | 534 | ## The ugly 535 | 536 | Nothing. 537 | 538 | # proxies 539 | 540 | ## What 541 | 542 | Literally proxy an object, and have control over what gets done to it: 543 | 544 | ``` 545 | var obj = {}; 546 | 547 | var proxy = new Proxy(obj, { 548 | get: function(target, propertyName){ 549 | return propertyName in obj ? obj[propertyName] : 'Never set!'; 550 | }, 551 | set: function(target, propertyName, value){ 552 | obj[propertyName] = value; 553 | } 554 | }); 555 | ``` 556 | 557 | Opens up the ability to create some nice apis: 558 | 559 | ``` 560 | var crel = new Proxy(actualCrel, { 561 | get: function(target, propertyName){ 562 | return target.bind(target, propertyName); 563 | } 564 | }) 565 | 566 | crel('div', {class: 'foo'}); // ->
567 | crel.div({class: 'foo'}); // -> 568 | ``` 569 | 570 | # symbols 571 | 572 | ## What 573 | 574 | like magical private strings that allow access to a property if you have the symbol 575 | 576 | ``` 577 | var mySymbol = Symbol('arbitraryString'); 578 | 579 | var obj = {}; 580 | 581 | obj[mySymbol] = 'foo'; 582 | 583 | // Can only be accessed if you have the instance of the symbol 584 | obj[mySymbol]; // -> 'foo' 585 | 586 | 587 | // Creating a new symbol with the same string will not work 588 | obj[Symbol('arbitraryString')]; // -> undefined 589 | ``` 590 | 591 | ## The good 592 | 593 | I'm not sure if these are really that useful. Maybe? You can do pretty much the same thing with WeakMap's and objects. 594 | 595 | Symbols are a little neater I guess 596 | 597 | ## The bad 598 | 599 | They are mostly sugar, but do add some legitimacy around privitized properties. 600 | 601 | ## The ugly 602 | 603 | Nothing really. 604 | 605 | # subclassable built-ins 606 | 607 | ## What 608 | 609 | You can now create constructors with Array/Date/Element prototypes 610 | 611 | ## The good 612 | 613 | This is an actual feature. This was previosuly hard/impossible to do properly. 614 | 615 | ## The bad 616 | 617 | Seems mostly good. 618 | 619 | ## The ugly 620 | 621 | There is a `@@create` property. It exists for a reason, but it's just ugly. 622 | 623 | # promises 624 | 625 | ## What 626 | 627 | Just callbacks but with crap around them to make sure you have no idea where an error came from. 628 | 629 | ## The good 630 | 631 | I honestly have never come across any situation where promises have looked like a good solution. 632 | 633 | ## The bad. 634 | 635 | ** BEGIN RANT ** 636 | 637 | ## The ugly 638 | 639 | ** CONTINUE RANT ** 640 | 641 | SHAMELESS PLUG: I made a thing that is what I'd have like promises to be: https://github.com/KoryNunn/righto 642 | 643 | # math + number + string + array + object APIs 644 | 645 | ## What 646 | 647 | There are new Math.x functions, like EPSILON, acosh, imul, hypot, isInteger, etc.. 648 | 649 | ## The good 650 | 651 | All looks good to me! 652 | 653 | # binary and octal literals 654 | 655 | ## They exist now: 656 | 657 | ``` 658 | 0b111110111 === 503 // true 659 | 0o767 === 503 // true 660 | ``` 661 | 662 | # tail calls 663 | 664 | ## What 665 | 666 | They work in certian situations now without adding stack. 667 | 668 | They seem fine. 669 | --------------------------------------------------------------------------------