ES6 note

面試又被電爆,所以寫一下筆記。當然會是動態擴充。

雖然不知道該寫在哪裡……

Arrow function

()=>{} ←就這玩意兒。這玩意兩種功能,一是語法簡潔化、二是把 this 放到外面一層的物件上。

function Person(){
  this.age = 0;
  setTimeout(()=>{
    this.age++;
  }, 1000);
}

var p = new Person();
console.log(p);
// 用 Babel 還原語法看看?

"use strict";
function Person() {
  var _this = this;

  this.age = 0;
  setTimeout(function () {
    _this.age++;
  }, 1000);
}

var p = new Person();
console.log(p);

感覺還蠻像是 Vue 的用法……

問題:_this 又是怎麼回事?


2018/04/30 增筆:在 JavaScript 裡面,變數的生效範圍,是以函式為單位。因此,為了讓 setTimeout(function () {}) 函式,能收到外面函式的 this,我們需要指派一個變數給 this 用。而這個變數,在這裡就是 _this

Ref: 重新認識 JavaScript: Day 10 函式 Functions 的基本概念

Class

語法糖。讓基於原型的 JavaScript 可以看起來像其他的物件導向一點。MDN

class Bar {
    constructor(baz) {
        this.baz = baz;
    }
}

class Foo extends Bar {
    constructor(ipt) {
        super(ipt);
        this.player = 2000;
    }
}

console.log(new Foo("Java")); // { baz:"Java" , player:2000 }

// 用 Babel 把語法解壓縮以後,發現長成這樣子:

"use strict";

function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}

var Bar = function Bar(baz) {
    _classCallCheck(this, Bar);

    this.baz = baz;
};

var Foo = function(_Bar) {
    _inherits(Foo, _Bar);

    function Foo(ipt) {
        _classCallCheck(this, Foo);

        var _this = _possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).call(this, ipt));

        _this.player = 2000;
        return _this;
    }

    return Foo;
}(Bar);

看到 _inherits 函式裡面的 subClass.prototype 了嗎?所以儘管 ES6 用上了 Class 這物件導向的語法,它還是基於原型的程式語言。

Enhanced Object Literals

var obj =
{
    __proto__: theProtoObj,
    ['__proto__']: somethingElse,
    handler,
    toString() {
     return "d " + super.toString();
    },
    [ "prop_" + (() => 42)() ]: 42
};

"use strict";
var _obj, _obj2;
var _get = function get(object, property, receiver)
{
    if (object === null) object = Function.prototype;
    var desc = Object.getOwnPropertyDescriptor(object, property);
    if (desc === undefined)
    {
        var parent = Object.getPrototypeOf(object);
        if (parent === null)
        {
            return undefined;
        }
        else
        {
            return get(parent, property, receiver);
        }
    }
    else if ("value" in desc)
    {
        return desc.value;
    }
    else
    {
        var getter = desc.get;
        if (getter === undefined)
        {
            return undefined;
        }
        return getter.call(receiver);
    }
};

function _defineProperty(obj, key, value)
{
    if (key in obj)
    {
        Object.defineProperty(obj, key
        , {
            value: value
            , enumerable: true
            , configurable: true
            , writable: true
        });
    }
    else
    {
        obj[key] = value;
    }
    return obj;
}
var obj = _obj = (_obj2 = {
    __proto__: theProtoObj
}, _obj2['__proto__'] = somethingElse, _defineProperty(_obj2, "handler", handler), _defineProperty(_obj2, "toString", function toString()
{
    return "d " + _get(_obj.__proto__ || Object.getPrototypeOf(_obj), "toString", this)
        .call(this);
}), _defineProperty(_obj2, "prop_" + function ()
{
    return 42;
}(), 42), _obj2);

這什麼東西?我不知道……

Template Strings

var x = "foo";
var y = "2000";

console.log( x + "bar" + y );
console.log( "I use \" " + x + "bar" + y + " \"." );
// 但你可以在 ES6 這樣寫……
console.log( `${x}bar${y}` );
console.log( `I use "${x}bar${y}".` );

// 注意到 ` 符號了嗎?就是這個關鍵字。

Destructuring

[] 這個看起來像是陣列的東西宣告多個變數。

var [ x , y , z ] = [ "x" , "y" ];
console.log( x , y , z ); // Shows: "x" , "y" , undefined
var [ a , b , ...c ] = [ 1 , 2 , 3 , 4 , 5 , 6 ];
console.log( a , b , c ); // Shows: 1 , 2 , [ 3 , 4 , 5 , 6 ]
// 反過來這樣會有語法錯誤:
var [ a , b , ...c , d ] = [ 1 , 2 , 3 , 4 , 5 , 6 ];
console.log( a , b , c , d ); // Error: rest element may not have a trailing comma

Let , Const

原本的 var 會全域生效,很容易被污染。但是在 ES6 裡面有兩種新的變數命名法:let 會只在被宣告的作用域內生效,而 const 在大多數情況下無法被變動。


參考資料