Khái niệm cơ bản trong JavaScript (2)

Trần Đức Lĩnh

Trong phần trước tớ đã giới thiệu các khái niệm cơ bản nhất bao gồm biến, vòng lặp, điều kiện, hàm,... và nó được minh hoạ bằng ngôn ngữ JavaScript. Trong bài tiếp theo, tớ muốn tìm hiểu sâu hơn để nắm bắt các khái niệm nền tảng.

You don’t know JS

1) Values & Types

Có một số type có sẵn trong JS:

  • Primitive types:

    • string
    • number
    • boolean
  • Special types:

    • null
    • undefined
    • NaN
  • Reference types:

    • object
    • array
    • symbol (ES6)

JS cung cấp cho chúng ta một hàm để kiểm tra kiểu dữ liệu thông qua cú pháp typeof.

  • Primitive types.

    • string (chuỗi)
    • number (số)
    • boolean (đúng sai)
var str = 'hello world';
var num = 10;
var boo_1 = true;
var boo_2 = false;

console.log(
    typeof str,
    typeof num,
    typeof boo_1,
    typeof boo_2

    // string number boolean boolean
)
  • Special types.

    • null mang giá trị (rỗng), nhưng thuộc về kiểu dữ liệu object.
    • undefined mang kiểu dữ liệu (không xác định).
    • NaN mang giá trị (không phải số - Not a Number ).
var nul = null;
var und = undefined;
var naN = NaN;

console.log(
    typeof nul,
    typeof und,
    typeof naN

    // object undefined number
)

Thú vị
Giá trị null sẽ trả về kiểu dữ liệu object trong khi bạn mong muốn nó trả về kiểu dữ liệu null như các kiểu dữ liệu khác.

var nu_obj = null;
typeof nu_obj;
// "object"

Cũng lưu ý rằng nếu bạn gán biến là undefined và khai báo biến không có giá trị đều cho ra kết quả là undefined.

var un_1;
typeof un_1;
// "undefined"
var un_2 = undefined;
typeof un_2;
// "undefined"
  • Reference types.

    • object

    Một object (đối tượng) trong JS là một kiểu dữ liệu phức tạp, nó cho phép chúng ta cài đặt nhiều giá trị thông qua PROPERTIES.

    PROPERTIES được truy xuất bằng.

    not notation hoặc bracket notation.

    var obj = {
        like: 'Orange'
    }
    
    console.log(obj.like);
    // not notation
    // Orange
    
    obj['like'] = 'Red';
    
    console.log(obj['like']);
    // bracket notation
    // Red

    Cách dùng thứ nhất có vẻ ngắn gọn hơn nhưng trong một số trương hợp cách dùng thứ hai lại tiện lợi hơn rất nhiều.

    Có một ví dụ thứ vị khi khai báo 1 biến tạm, trùng với key của object.

    var obj = {
        a: "hello world",
        b: 197
    };
    
    var b = "a";
    
    console.log(obj[b]);
    // <. obj[b]
    // .> "hello world
    console.log(obj["b"]);
    // <. obj["b"]
    // .> 197
    • array

    Mảng là một đối tượng chứa các giá trị không dùng đến key/values, mà chỉ dùng đến chỉ số index để truy cập đến các phân tử. Phần tử đầu tiên được đếm từ số 0.

    var obj_1 = {
        colour: 'Red',
    }
    
    var obj_2 = {
        colour: 'Blue',
    }
    
    var obj_3 = {
        colour: 'Green',
    }
    
    var arr = [obj_1, obj_2, obj_3];
    
    for(let i = 0; i< arr.length; i++) {
        console.log(arr[i].colour);
        // Reb, BLue, Yellow.
    }
    
    var hexColour = ['#ff0000', '#0000ff', '#00ff00'];
    
    for (let i = 0; i < arr.length; i++) {
        arr[i].colour = hexColour[i];
    
        console.log(arr[i].colour);
        // #ff0000, #0000ff, #00ff00
    }

    Ví dụ cụ thể hơn.

    var arr = [
    {colour: 'Red', hexColour: '#ff0000'},
    {colour: 'Green', hexColour: '#00ff00'},
    {colour: 'Blue', hexColour: '#0000ff'},
    ];
    
    // Vong lap thong thuong
    for (let i = 0; i < arr.length; i++) {
        console.log(i);
        // 0 1 2
    }
    
    // Lay chi so
    for (const arr_in in arr) {
        console.log(arr_in);
        // 0 1 2
    }
    
    // Lay phan tu trong mang
    for (const arr_of of arr) {
        console.log(arr_of);
        // { colour: 'Red', hexColour: '#ff0000' }
        // { colour: 'Green', hexColour: '#00ff00' }
        // { colour: 'Blue', hexColour: '#0000ff' }
    }
    
    // Duyet qua tung phan tu trong mang
    arr.forEach(arr_each =>
        console.log(arr_each)
        // { colour: 'Red', hexColour: '#ff0000' }
        // { colour: 'Green', hexColour: '#00ff00' }
        // { colour: 'Blue', hexColour: '#0000ff' }
    );

    Lưu ý thêm lần nữa chỉ số index được bắt đầu từ 0.

Functions

Là một dạng đặc biệt của object. Thường có một hoặc nhiều tham số truyền vào (hoặc không có), bên trong có chứa các câu lệnh và return để trả về giá trị nào đó ra bên ngoài function.

Có 2 cách để khai báo một function gồm.

  • Function Statement/Declarations

    Khai báo tên function nằm trong function chứa nó.

    Đưa đến bất kỳ vị trí nào cũng đều không gặp lỗi.

function func(x) {
    console.log(x);
    // hello
};

var a = 'hello';

func(a);
  • Function Expression

    Gán functions cho một biến đã tạo trước đó liền nhau.

    Nếu đưa console.log(func(a)); lên dòng đầu sẽ xuất hiện lỗi.

var func = function (x) {
    return x;
};

var a = 'hi';

console.log(func(a));
  • Function Constructor

    Kiểu functions này được khai báo tương tự như Functions Expression, nhưng được khai báo dưới từ khóa new.

    Ít khi được dùng trong JS, nhưng vẫn được đề cập đến.

const func = new Function("x", "return ++x");

func(10);
// 11

Yield

Generator function là một function, có khả năng tạm ngưng thực thi trước khi hàm kết thúc, và có thể tiếp tục chạy ở 1 thời điểm khác.

Ví dụ 1: Tính toán đơn giản.

function* Op(name) {
    yield name * 5; // Thực thi lần thứ 1
    yield name; // Thực thi lần thứ 2
}

const call = Op(4);
console.log(call.next().value); // Lần gọi thứ 1
console.log(call.next().value); // Lần gọi thứ 2

// 20
// 4

Object method (object literal)

Là các phương thức của Object, bên trong object có thể chứa function.

var objMethod = {
colour: 'red',
hex: function(x) {
    console.log(x);
    // #ff0000
    }
};

console.log(objMethod.colour);
// red

objMethod.hex('#ff0000');

Object Constructors (Constructor function)

Xây dựng một đối tượng nhanh hơn so với Object method. Sử dụng cú pháp new để tạo đối tượng.

function Chicken(color, weight) {
    this.type = 'chicken';
    this.color = color;
    this.weight = `${weight}kg`;
};

const chicken_1 = new Chicken ('yellow', 1.2);
const chicken_2 = new Chicken ('orange', 2);

console.log(chicken_1);
// Chicken { type: 'chicken', color: 'yellow', weight: '1.2kg' }
console.log(chicken_2);
// Chicken { type: 'chicken', color: 'orange', weight: '2kg' }

Built-in Type Methods

Những kiểu dữ liệu đã đề cập phía trên thông thường có (properties & methods).

Mỗi một kiểu dữ liệu trong JS đều thừa kế một object nào đó. Cùng xem ví dụ cụ thể.

var buil = "hello world";
console.log(buil.length);
// 11
console.log(buil.toUpperCase());
// "HELLO WORLD"
  • Biến a là chuỗi, nó sẽ thừa hưởng những phương thức (methods) từ cha của nó là String.
    Với string JS hỗ trợ nhiều thuộc tính (properties) như: .length; .toUpperCase();...

Tương tự với Number, Array JS cũng hỗ trợ nhiều dạng thuộc tính có thể sử dụng bao gồm: .push(); .pop(); .map(); .filter(); .reduce();

Comparing Values

Có hai dạng so sánh bằng nhau và không bằng nhau. Giá trị trả về luôn là true hoặc false.

var comp = 5;
console.log(comp === 5);
// true
console.log(comp != 5);
// false

Coercion

Ở bài trước có nhắc sơ qua 2 dạng ép kiểu gồm: explicitimplicit.

Explicit là dạng ép kiểu một giá trị theo cách bản thân muốn, khi ép kiểu ở dạng này ta dễ dàng nhận biết và chủ động được điều này.

var expl = "11";
console.log(Number(expl) + 1);
// 12

Implicit là dạng ép kiểu ngầm định bên trong JS, chúng tự giúp chúng ta chuyển đổi kiểu dữ liệu và không thể kiểm soát được những sự thay đổi đó.

var imp_1 = null;
var imp_2 = null;
console.log(ipm_1 + imp_2);
// 0
// "number"

Đôi lúc chính dạng ép kiểu Implicit trả về kết quả không mong muốn.

Trutly & Falsy

Trước đó đã đề cập sơ lượt về Boolean. Có 2 dạng giá trị gồm truefalse. Ở một số trường hợp JS sẽ ép kiểu một số dữ liệu khác kiểu Boolean, một số ví dụ sẽ trả về false.

// "" (empty string)
// 0; -0; NaN
// null; undefined
//  false

Nhưng một số kiểu dữ liệu lại trả về true.

// "text";
// 197;
// []; [1,"text",]; (array)
// {}; {a: 197}; (object)
// function opp() { // code here }; (function)

Equality

Có một số toán tử so sánh như: ==; ===; !=; !== trong đó ! mang ý nghĩa phủ định (not).

Sự khác nhau giữa ===== thường được hiểu là:

  • == so sánh về giá trị.
  • === so sánh giá trị và kiểu dữ liệu.

Nhưng thực chất vẫn không đúng khi JS sẽ tự động ép kiểu dữ liệu để so sánh.

var str = "197"
var num = 197;
str == num;
// true
str === num;
// false

Ví dụ trên, JS sẽ ép kiểu dữ liệu khi so sánh giá trị (==) từ dạng string == number -> number == number để so sánh. Và kết quả sẽ là true.
Trong khi so sánh (===) sẽ khắc khe hơn khi không cho ép kiểu dữ liệu, khác kiểu dữ liệu nên kết quae sẽ là false.

Variables

Trong các ngôn ngữ lập trình, việc đặt tên biến bao gồm cã tên hàm đều phải theo chuẩn. Phải bắt đầu bằng (a-z, A-Z, $, _). Sau đó có thể bao gồm các ký tự bất kỳ hay chữ số từ (0-9).

Lưu ý rằng việc đặt tên không được trùng với các từ khoá như: if; else; case; do; break;...

Functions scopes

Mỗi function đều có một tầm vực riêng biệt. Khi ra khỏi tầm vực thì không thể truy cập được nhưng biến bên trong.

Function scopes sẽ qui định một phạm vi truy cập và thực thi một hàm.

Có thể sử dụng var để khai báo một biến thuộc về một function hoặc nếu khai báo một biến nằm ngoài tất cả các hàm thì nó sẽ là global scope.

Hoisting

Hoisting là một hành động mặc định của JS, nó sẽ đưa các khai báo biến lên phần đầu tiên của phạm vi mà biến được sử dụng.

Chỉ có phần khai báo biến được đưa lên trên cùng, không phải phần khai báo giá trị.

Phần khai báo hàm được đưa lên trước phần khai báo biến.

console.log(x);
// ReferenceError: x is not defined;

Khi đó biến x sẽ lỗi vì không khai báo trước khi chạy dòng console.log().

Hoặc thay đổi vị trí trước sau và không khai variables cũng có kết quả tương tự.

console.log(x);
x = 'Hoisting';
// ReferenceError: x is not defined;
  • Nhưng khi gán variables cho từng mục như trên thì đều trả về kết quả undefined.
var x;
console.log(x);
// undefined

console.log(x);
var x;
// undefined

Nhưng hãy lưu ý rằng, nếu dựa vào hoisting để triển khai là một ý tưởng tồi. Nó có thể dẫn đến nhầm lẫn và không tường minh. Trong bài viết (Tìm hiểu ES6) có nói về việc từ bỏ việc sử dụng var và nên dùng letconst.

Riêng trong trường hợp với function có thể phổ biến hơn và chúng có thể sử dụng hoisting.

func("Hoisting");

function func(x) {
    console.log(x);
    // Hoisting
};

Khi tạo biến bên trong function thì giới hạn phạm vi của biến chỉ nằm bên trong nó, sẽ xuất hiện lỗi như trên.

func();

function func() {
    console.log(x);
    var x;
    // undefined
};

Conditionals

Điều kiện trong JS có thể hiểu khái quát là (if-else). Bên cạnh đó có thể sử dụng các cú pháp tương tự để làm việc.

  • Sử dụng if-else.
if(num == 2) {
    // code here
}
else if (num == 4) {
    // code here
}
else {
    // code here
}
  • Sử dụng switch-case.
switch(num) {
    case 2: 
        // code here 
        break;
    case 4:
        // code here
        break;
    default:
};
  • Trong một số trường hợp có thể sử dụng toán tử 3 ngôi để rút gọn code.
const num = 2;
(num < 4) ? console.log("true") : console.log("false");
// true

Strict mode

Strict mode được thêm vào ở phiên bản ES5, có chức năng kiểm tra cú pháp, giảm lỗi và tăng tính năng bảo mật.

JS cung cấp và sử dụng strict mode với cú pháp

"use strict";

Lưu ý khi sử dụng Strict mode.

  • Không được dùng với biến "undefined".
  • Không đặt tên trùng với từ khoá.
  • Không đặt 2 thuộc tính trùng nhau trong 1 object.
  • Không truyền 2 tham số cùng tên nhau trong 1 function.
  • Không định nghĩa trên cơ số 8.
  • Không được dùng câu lênh with. Gán giá trị trong một thuộc tính read-only trong đối tượng.
  • Thay đổi đối số trong object.
  • EVAL không được phép tạo biến.

Function As Values

Khi khai báo một Functions trong JS, kiểu khai báo như thế này đã đề cập đến phần trước.

Những kiểu khai báo một hàm thông thường được gọi là Function Declaration. Những hàm kiểu như thế này có thể được gọi trước khi khai báo hoặc sau khi khai báo đều được.

function opp() {
    // code here
};

Trước khi đi sau vào 2 phần dưới, bao gồm hàm có dạng Anomymous FuntionsNamed Function Expressions đều có dạng là Functions Expressions. Khác với những kiểu khai báo thông thường, việc gọi hàm khi được sử dụng phải theo trình tự rõ ràng.

  • a) Anonymous Functions

Function có dạng Anonymous Functions hay được gọi là một hàm ẩn danh. Thông thường khi khai báo một hàm thì chương trình biên dịch sẽ lưu lại trong bộ nhớ, vì thế có thể gọi phía trên hay ngay phía dưới vị trí khai báo hàm đều được. Nhưng đối với Anonymous functions thì được sinh ra khi biên dịch và xử lý tới vị trí của nó.

var foo = function() {
    // code here
};

Thông thường anonymous functions thường được sử dụng để thực hiện một callback function.

  • b) Named Function Expressions

Kiểu khai báo có tên và được gán cho biến là một điển hình của Functions Expressions.

var foo = function opp() {
    // code here
};
  • Callback function

Truyền một hàm vào bên trong hàm khác với tư cách là một tham số, khi đó hàm được truyền vào được gọi là callback. Tham số này sẽ được gọi lại sau khi thực hiện các đoạn code trước đó.

function my_func (param) {
    if (typeof param === 'function') {
        param("hello");
    }
}

function my_call (value) {
    console.log(value);
}

my_func(my_call)

Function


Immediately Invoked Function Expressions (IIFEs)

Có nhiều tài liệu gọi loại function này là Self-Invoking Functions.

IIFEs này cũng là một functions, khi chúng ta khai báo hàm nó sẽ thực thi ngay tức khắc. Cú pháp rất lạ và cũng khó nhớ.

(function opp() {
    console.log(0.1 + 0.2 == 0.3);
    // false
})();

Trong dấu ngoặc (...) bao quanh hàm chỉ là cú pháp để phân biệt với những functions thông thường khác.
Hai kiểu functions bên dưới đều tương tự nhau.

function foo(){
    // code here
}
foo();

// -------

(function IIFE() {
    // code here
})();

Lý do tạo ra IIFEs bởi vì nó sẽ tạo ra một scope riêng cho nó. Khi bạn vô tình khai báo một biến trùng với tên khai báo biến bên ngoài thì cũng không ảnh hưởng gì.

var efi = 10;

(function IIFE() {
    var efi = 100;
    console.log(efi);
    // 100
})();

console.log(efi);
// 10

Và tất nhiên cũng có thể return về một giá trị trong IIFEs.

const efi = (function IIFE() {
    return 100;
})();

efi;
// 100

Promise

Khi xử lý yêu cầu từ file lớn hoặc gửi yêu cầu lên SERVER đa số đều rất tốn thời gian.
Thay vì chờ đợi xử lý xong, ta có thể nhờ promise làm các vấn đề tiếp theo sau đó mà không phải chờ đợi.
Giải quyết vấn đề callback hell trong JS.

Cú pháp: new Promise(function(resolve, reject) { ... } );

if(){
    if(){
        if(){
            ...
        }
    }
}

Khắc phục điều đó, promise sẽ thực hiện và làm code sạch hơn.

var time = function(length) {
    return new Promise (function (resolve, reject) {
        setTimeout(function () {
            if(length > 10000) {
                reject ('Quá lâu để chờ đợi! \n Thời gian thực hiện là ' + length/1000 + ' giây!');
            }
            else {
                resolve ('Thời gian thực hiện ' + length/1000 + ' giây!');
            }
        }, length);
    });
}

time (15000).then(function(val) {
    console.log('Có vẻ yêu cầu đã thành công! ' + val);
    
    // ERROR !!! Quá lâu để chờ đợi! 
    // Thời gian thực hiện là 15 giây!
    
}).catch (function (val) {
    console.log('ERROR !!! ' + val);
});

time (5000).then(function(val) {
    console.log('Có vẻ yêu cầu đã thành công! ' + val);
    
    // Có vẻ yêu cầu đã thành công! Thời gian thực hiện 5 giây!
    
}).catch (function (val) {
    console.log('ERROR !!! ' + val);
});

time (3000).then(function(val) {
    console.log('Có vẻ yêu cầu đã thành công! ' + val);
    
    // Có vẻ yêu cầu đã thành công! Thời gian thực hiện 3 giây!
    
}).catch (function (val) {
    console.log('ERROR !!! ' + val);
});

time (1000).then(function(val) {
    console.log('Có vẻ yêu cầu đã thành công! ' + val);
    
    // Có vẻ yêu cầu đã thành công! Thời gian thực hiện 1 giây!
    
}).catch (function (val) {
    console.log('ERROR !!! ' + val);
});

Closure

Phần này là những phần quan trọng và đặc biệt nhất trong JavaScript. Tuy vậy nhưng vẫn có nhiều người bỏ qua phần này nhất.
Trong bài viết Bạn nên biết Closure hoạt động như thế nào! sẽ nói rõ hơn về cơ chế của nó. Trong bài viết này, tớ chỉ điểm sơ qua những nét cơ bản để có cái nhìn tổng quát và toàn diện hơn.

Closure là một cách để nhớ và truy cập scope của function (bao gồm những biến bên trong function) khi mà function đã thực thi xong.

Đối với những function thông thường, sau khi thực thi xong, những biến đó sẽ được xóa khỏi bộ nhớ. Nhưng đối với Closure thì không, những biến bên trong một function vẫn có thể lưu lại và truy xuất ngay cã khi function đó đã thực thi xong.

Ví dụ đơn giản.

Khi thực hiện xong function phía đưới, bộ nhớ sẽ được giải phóng ngay sau đó.

function closure(a,b) {
    const c = a + b;
    return console.log(c);
};

closure(5,8);
// 13

Nhưng khi đưa giá trị vào bên trong function, giá trị đó sẽ được truy cập từ các biến ở bên ngoài và thay đổi chúng.

Hoặc ví dụ cụ thể hơn.

  • Khi gọi block_1(10), hàm này sẽ trả về hàm bên trong block_2 và nó sẽ nhớ giá trị x được truyền vào là 10.
  • Sau đó gọi biến add(20), nó sẽ truyền cho biến y với giá trị là 20. Bên trong block_2 sẽ cộng 2 biến và trả về giá trị là 30.
function closure(a,b) {
    const c = a + b;
    return function () {
        console.log(c);
    }
};

closure(5,8)();
// 13
function block_1 (x) {
    function block_2 (y) {
        return x + y;
    };
    return block_2;
};
var add = block_1(10);
add(20);
// 30

Modules

Những ứng dụng phổ biến trong Closure là dùng để tạo các modules. Bằng cách tạo những API cho một chức năng gì đó cho việc xử lý định dạng ngày tháng.

This.

Tìm hiểu sâu hơn về THIS trong JavaScript.

this không chỉ liên quan đến OOP mà những gì this là được còn to lớn hơn nhiều.

this có thể trỏ đến 1 đối tượng nào đó. Và những đối tượng đó được gọi như thế nào, this được nhận biết trong khi function đó được gọi trong ngữ cảnh nào bao gồm: global hay object.

Đáng chú ý là this không liên kết với hàm của chính nó.

var animal = {
    name: 'cat',
    getContent: function() {
        console.log(this.name);
        // 'cat'
        console.log(animal.name);
        // 'cat'
    }
};

animal.getContent();

Prototypes

Prototypes trong JS rất phức tạp.

Khi muốn truy xuất một thuộc tính của một đối tượng (object) nào đó bên trong JS, nếu thuộc tính đó không tồn tại, JS sẽ tự động sử dụng một liên kết bên trong object đó để tìm thuộc tính không tồn tại trước đó.

Thường sử dụng prototype trong JS để tạo sự thừa kế của các đối tượng với nhau.

Có liên quan đến Object Constructors (Constructor function) khi sử dụng từ khóa new.

function Human (skin, hair, sex) {
    this.skin = skin;
    this.hair = hair;
    this.sex = sex;
};

Human.prototype.goodlooking = function() {
    console.log(`${this.sex} good-looking!!!`);
};

const human_1 = new Human('white', 'brown', 'girl');
const human_2 = new Human('orange', 'black', 'boy');

console.log(human_1);
// Human { skin: 'white', hair: 'brown', sex: 'girl' }
human_1.goodlooking();
// girl good-looking!!!

console.log(human_2);
// Human { skin: 'orange', hair: 'black', sex: 'boy' }
human_2.goodlooking();
// boy good-looking!!!

Class

Kế thừa kiểu của Prototype, được thiết kế để thiết kế trong dễ nhìn hơn.

class Human {
    constructor(skin, hair, sex) {
        this.skin = skin;
        this.hair = hair;
        this.sex = sex;
    }
    goodlooking() {
        console.log(`${this.sex} good-looking!!!`);
    }
}

const human_1 = new Human('white', 'brown', 'girl');
const human_2 = new Human('orange', 'black', 'boy');

console.log(human_1);
// Human { skin: 'white', hair: 'brown', sex: 'girl' }
human_1.goodlooking();
// girl good-looking!!!

console.log(human_2);
// Human { skin: 'orange', hair: 'black', sex: 'boy' }
human_2.goodlooking();
// boy good-looking!!!

Class inheritance

Một cách kế thừa các thuộc tính từ class.

class Human {
    constructor (sex) {
        this.sex = sex;
    }

    callSex() {
        console.log(`Hey!!! ${this.sex}`);
    }
};

class Boy extends Human {
    beard() {
        console.log('Long beard...');
    }
};

const a = new Boy ('Gken');

a.callSex();
a.beard();

// Hey!!! Gken
// Long beard...

Old & New

Tại thời điểm hiện tại tớ viết blog này thì có rất nhiều browser khác nhau: Chrome, Safari, Firefox, Edge, Opera,...

Bài toán đặt ra phải làm như thế nào chạy tốt trên tất cả các trình duyệt trên.

Có 2 kỹ thuật chính để sử dụng sự mới mẻ của JS trên những trình duyệt cũ hơn đó là: polyfilling và transpilling.

Polyfilly

Cách kiểm tra xem function có hỗ trợ trên trình duyệt cũ hay không.

if (!Number.isNaN) {
    Number.isNaN = function isNaN(a) {
        return a !== a;
    };
}

Transpilling

Cách sử dụng công cụ để chuyển đổi cú pháp mới sang cú pháp cũ hơn.

function foo(a = 10) {
	console.log( a );
}

foo();		// 10
foo( 200 );	// 200

Đoạn code phía trên là ES6, nhưng các trình duyệt cũ hơn sẽ không hỗ trợ đọc được function như trên, vì thế ta cần 1 công cụ để chuyển chúng thành đoạn mã như sau.

function foo() {
  var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;
  console.log(a);
}

foo();		// 10
foo( 200 );	// 200

Babeljs giúp chuyển đổi từ ES6 sang ES5 một cách đơn giản hơn nhiều.

Non-JavaScript

Thao tác DOM là một thành phần mà chính JS không quản lý ở mức global bao gồm: document, window, alert, console,... Những thành phần trên được browser tạo ra nhằm thao tác với DOM.

alert('Hello word!');

Có thể truy cập vào đây để tìm hiểu kỹ hơn.