Chào các bạn, hôm nay anh sẽ hướng dẫn mọi người về khi nào không nên sử dụng Arrow function của ES6. Lần lượt giới thiệu và và đi qua các ví dụ về các trường hợp không nên dùng nó. Trong 5 trường hợp sau thì chúng ta không nên dùng arrow function để code vì arrow function không sở hữu giá trị this.
Anh có ví dụ sau đây, người dùng sẽ điền giá trị vào input sau đó anh lấy giá trị đó hiển thị ra ở một thẻ div như sau
Anh tạo một thẻ input để lấy tên người dùng.
1
<input type="text" name="username" id="username" placeholder="Enter a username">
Anh tạo một thẻ div để hiển thị tên người dùng lấy được từ input
1
<div id="greeting"></div>
Anh viết đoạn mã javascript để lấy tên người dùng và gán vào thẻ div như sau
1
2
3
4
5
6
7
8
9
const greeting = document.querySelector('#greeting');
const username = document.querySelector('#username');
username.addEventListener('keyup', () => {
greeting.textContent = 'Hello ' + this.value;
});
Tuy nhiên khi chương trình chạy anh sẽ nhận được kết quả là ‘Hello’ undefined. Có nghĩa là this.value lấy không được giá trị trong hàm bắt sự kiện addEventListener. Như đã nói trong phần mở đầu arrow function không sở hữu phạm vi biến this của input, chính vì vậy mặc dùng ta ghi this.value thì ta ngầm định this này chính là của input nhưng thật sư không phải.
Để sửa lại đoạn code trên có thể bắt được sự kiện từ input thì ta phải dùng cách viết bình thường của javascript không dùng arrow function như sau.
1
2
3
username.addEventListener('keyup', function () {
input.textContent = 'Hello ' + this.value;
});
Anh ví dụ có đối tượng Counter như sau.
1
2
3
4
5
const counter = {
count: 0,
next: () => ++this.count,
current: () => this.count
};
Đối tượng counter có 2 phương thức là next và current. Phương thức next để lấy giá trị tiếp theo và current là lấy giá trị hiện tại. Anh sẽ gọi phương thức next của đối tượng counter như sau.
1
console.log(counter.next());
Như vậy kết quả anh muốn muốn sẽ là 1. Tuy nhiên khi chương trình chạy anh sẽ nhận được kết quả là NaN. Nguyên nhân khi anh sử dụng this.count thì khi đó biến this này đang hiểu là đối tượng window chứ không phải là đối tượng counter. Để tránh biến this tham chiếu tới phạm vi toàn cục (global) thì ta sửa lại đoạn code trên như sau.
1
2
3
4
5
6
7
8
9
const counter = {
count: 0,
next() {
return ++this.count;
},
current() {
return this.count;
}
};
Chúng ta bỏ khai báo arrow function đi và viết theo cách viết bình thường.
Tương tụ như trường hợp phương thức trong đối tượng thì phương thức trong class chúng ta cũng không dùng arrow function.
1
2
3
4
5
6
7
8
9
10
11
class Counter {
constructor() {
this.count = 0;
}
next = () => {
return ++this.count;
}
current = () => {
return this.count;
}
}
Chúng ta không khai báo theo kiểu arrow function trong Class mà khai báo theo cách sau đây.
1
2
3
4
5
6
7
8
9
10
11
class Counter {
constructor() {
this.count = 0;
}
next() {
return ++this.count;
}
current() {
return this.count;
}
}
Chúng ta lấy ví dụ về prototype cho đối tượng counter như sau
1
2
3
4
5
6
7
8
9
10
11
function Counter() {
this.count = 0;
}
Counter.prototype.next = () => {
return this.count;
};
Counter.prototype.current = () => {
return ++this.next;
}
Thì giá trị this.next và this.current đang tham chiếu tới đối tượng cục bộ (global) chứ không phải đối tượng counter. Chúng ta sẽ modify đoạn code trên lại như sau để this có thể tham chiếu đến counter.
1
2
3
4
5
6
7
8
9
10
11
function Counter() {
this.count = 0;
}
Counter.prototype.next = function () {
return this.count;
};
Counter.prototype.current = function () {
return ++this.next;
}
Anh có ví dụ sau
1
2
3
4
const concat = (separator) => {
let args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}
Thay vì dùng theo arrow function thì ta nên thay đổi lại như sau
1
2
3
4
function concat(separator) {
let args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}