Những chức năng mới của ES6

Phiên bản mới của Javascript đã ra đời được một thời gian rồi, mình cũng có làm qua nhưng chưa thực sự chú ý nhiều, chủ yếu vẫn viết theo kiểu cũ. Nay mình mới đọc lại một số tài liệu, hướng dẫn và tống hợp lại những chức năng thú vị của ES6.

Template string

Với chức năng này ta có thể tạo một bản mẫu cho chuỗi cho phép ta nhúng các biểu thức vào, và cũng có thể viết trên nhiều dòng. Chú ý là ta sẽ dùng dấu ` chứ không phải dấu ‘, dấu này ở ngay dưới phím Esc trên bàn phím.

Cách dùng

1
2
3
4
var country = 'vietnam';
var str = `Xin chao ${country}
phep tinh 1 + 2 = ${1+2}`;
console.log(str);

Kết quả

1
2
Xin chao vietnam
phep tinh 1 + 2 = 3

Destructuring assignment (Tách và gán)

Tách và gán là mình tự dịch ra thôi, chức năng này cho phép ta trích xuất dữ liệu từ mảng hoặc đối tượng gán vào các biến riêng lẽ.

Cách dùng

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [1, 2, 3];
var [one, two, three] = arr;
console.log('one is', one); // => one is 1
console.log('two is', two); // => two is 2
console.log('three is', three); // => three is 3
// Lấy 1 phần của mảng
var [a, ...rest] = arr;
console.log(a); // => 1
console.log(rest); // => [2,3]
var obj = {name: 'thach', age: 27};
var {name, age} = obj;
console.log('name is', name); // => name is thach
console.log('age is', age); // => age is 27

Lấy kết quả trả về từ hàm

1
2
3
4
5
6
function getTop2() {
return ['hai', 'ha'];
}
var [p1, p2] = getTop2();
console.log(p1); // hai
console.log(p2); // ha

Gán cho một biến khác tên với thuộc tính của đổi tượng

1
2
3
var obj = {name: 'thach', age: 27};
var {name: n, age: a} = obj;
console.log(n, a); // thach 27

Block scope với let

let cho phép ta tạo ra một biến được giới hạn trong phạm vi của block chứa nó. let khác với var ở chỗ, var tạo ra một biến có phạm vi toàn cục hoặc xuyên suốt một hàm. Để rõ hơn thì mình coi qua ví dụ so sánh giữa letvar.

1
2
3
4
5
6
7
8
9
10
if (true) {
// Đây là 1 block của if
var a = 'foo';
let b = 'bar';
console.log(a); // foo
console.log(b); // bar
}
console.log(a); // foo
console.log(b); // Error: Uncaught ReferenceError: b is not defined

Như ta thấy ở ví dụ trên, biến b chỉ có thể dùng trong if-block mà không thể dùng bên ngoài được. Bây giờ ta tiếp tục ví dụ với hàm.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function varFunc() {
var x = 1;
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
}
function letFunc() {
let y = 1;
if (true) {
let y = 2;
console.log(y); // 2
}
console.log(y); // 1
}
varFunc();
letFunc();

Khi ta let y = 2 bên trong if-block nó tạo ra một biến y mới không liên quan gì đến let y = 1 ở trên cả. cho nên sau if-block, y bên ngoài không bị thay đổi.

Dùng let với bất đồng bộ

Hãy xem ví dụ sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for (var i = 0; i < 3; i ++) {
setTimeout(function() {
console.log('var', i);
});
}
// var 3
// var 3
// var 3
for (let i = 0; i < 3; i ++) {
setTimeout(function() {
console.log('var', i);
});
}
// var 0
// var 1
// var 2

Nếu ta dùng var ở trên, sau khi 3 vòng lặp thực hiện xong, 3 dòng console.log bên trong setTimeout sẽ được thực thi, khi đó in ra giá trị i lúc này đã là 3 rồi, cho nên ta có 3 nội dung var 3 giống nhau.

Tuy nhiên nếu dùng let như ở dưới, mỗi vòng lặp tạo ra một biến i không liên quan gì đến nhau, cho nên ta có 3 nội dung in ra khác nhau.

Vì vậy, ta thấy dùng let sẽ giúp cho code rõ ràng hơn trong trường hợp này, tránh phải sai lầm không mong muốn.

Const

Coi về let rồi thì tranh thủ coi về const 1 chút luôn. const giúp ta định nghĩa một biến với giá trị không thể thay đổi.

1
2
const a = 'foo';
a = 'bar'; // Error: Uncaught TypeError: Assignment to constant variable.

Class

Khi trước để tạo một giả class trong js ta sẽ dùng function, như thế này:

1
2
3
4
5
6
7
8
9
10
function Person() {
// ....
}
Person.prototype.hello = function() {
console.log('hello');
}
var p1 = new Person();
p1.hello(); // hello

Nay với ES6, ta có class, giúp ta có thể tạo lớp, đối tượng, làm việc với kế thừa một cách đơn giản hơn.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person {
constructor (name) {
this.name = name;
}
speak() {
console.log('My name is', this.name);
}
// static method có thể được gọi mà không cần đến đối tượng của class
static sayHello() {
console.log('Hello');
}
}
var p1 = new Person('Viet');
p1.speak(); // My name is Viet
Person.sayHello(); // Hello

Tạo một class con với extends

Để tạo một class con của một class ta dùng extends.

1
2
3
4
5
6
7
8
class Teacher extends Person {
speak() {
console.log('My name is', this.name, 'I am a teacher');
}
}
var p2 = new Teacher('Hai');
p2.speak(); // My name is Hai I am a teacher

Nếu trong lớp con có constructor thì ta phải gọi phương thức super() trước khi sử dụng this.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Student extends Person {
constructor(name, school) {
super(name);
this.school = school;
}
speak() {
console.log('My name is', this.name, 'I am studying in', this.school);
}
}
var p3 = new Student('Minh', 'ST');
p3.speak(); // My name is Minh I am studying in ST

Arrow functions

Một cách viết hàm mới, ngắn gọn hơn.

Dưới đây là ví dụ so sánh giữa cách viết cũ và mới.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ES5
[1,2,3].map(function (num) { return num * 2; })
// => [2, 4, 6]
// ES6
[1,2,3].map((num) => { return num * 2; })
// => [2, 4, 6]
// Vì chỉ có 1 tham số num nên ta có thể bỏ dấu ngoặc đơn luôn
[1,2,3].map(num => { return num * 2; })
// => [2, 4, 6]
// Nhưng ở đây cũng chỉ có mỗi lệnh return nên ta có thể bỏ luôn dấu ngoặc nhọn và return
[1,2,3].map(num => num * 2)
// => [2, 4, 6]

Nếu như hàm có nhiều tham số, và có nhiều dòng lệnh hơn thì ta viết đầy đủ thế này:

1
2
3
4
5
6
7
8
[1,2,3].map((num, index) => {
console.log(index);
return num * 2;
});
// 0
// 1
// 2
// => [2, 4, 6]

Trả về một object

Chú ý nếu muốn trả về một object ta không chỉ đơn giản dùng { key: value } được.

1
2
3
4
5
var func1 = () => { name: 'saysua' };
func1(); // undefined
var func2 = () => { name: 'saysua', age: 3 };
func2(); // Error: Uncaught SyntaxError

Lỗi ở đây là do, ở giữa cặp dấu ngoặc nhọn {} code sẽ được hiểu là một chuỗi các câu lệnh. Như ở func1, name được hiểu là 1 label chứ không phải là một key của object. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label)

Ta viết lại cho đúng như sau:

1
2
3
4
5
var func1 = () => ({ name: 'saysua' });
func1(); // => Object {name: "saysua"}
var func2 = () => ({ name: 'saysua', age: 3 });
func2(); // => Object {name: "saysua", age: 3}

Arrow function không tự động bind this

Nếu ở ES5 ta tạo một hàm mới, nó sẽ luôn tự tạo ra một giá trị this vì vậy code dưới đây sẽ chạy bị sai.

1
2
3
4
5
6
7
8
9
function Runner() {
this.count = 1;
setTimeout(function() {
this.count ++; // this ở đây không phải là this ở trên nên this.count không tồn tại
console.log(this.count); // NaN
}, 100);
}
var r = new Runner();

Ta sẽ thường xử lý bằng cách gán một biến that = this hoặc là bind(this) vào hàm bên trong.

1
2
3
4
5
6
7
8
9
10
11
function Runner() {
var that = this;
this.count = 1;
setTimeout(function() {
that.count ++;
console.log(that.count); // 2
}, 100);
}
var r = new Runner();

Còn arrow function không tự động tạo giá trị this nên đoạn code sau sẽ chạy đúng như ta mong muốn.

1
2
3
4
5
6
7
8
9
function Runner() {
this.count = 1;
setTimeout(() => {
this.count ++;
console.log(this.count); // 2
}, 100);
}
var r = new Runner();

Tuy nhiên, chính vì đặc tính này mà bạn cần phải chú ý khi sử dụng arrow function trong một số trường hợp, ví dụ:

1
2
3
4
5
6
7
8
9
10
var sum = {
a: 1,
b: 2,
run: () => {
console.log(this === window); // => true (this không phải là sum)
return this.a + this.b; // NaN (nên this.a và this.b không có)
}
};
sum.run();

Tổng kết

Mình thấy những tính năng mới của ES6 rất thú vị, giúp viết code nhanh và vui hơn, vẫn còn nhiều tính năng mới nữa nhưng mình chưa tìm hiểu hết được. Tuy nhiên một vài trường hợp cần phải sử dụng cẩn thận, kẻo nhanh quá lại hóa sai, không kiểm soát được các giá trị. Happy codding!


Lưu log của nginx vào elastic search bằng logstash

Thông thường, mỗi truy cập vào nginx đều được lưu vào file log, ví dụ /var/log/nginx/access.log. Tại đây, ta có thể coi các thông tin về truy cập như thời gian, đường dẫn, trình duyệt của người dùng.

Nhưng nếu ta cần có thống kê chi tiết hơn về các truy cập này, như số lượt truy cập trong ngày, phân loại người dùng … thì file log này là chưa đủ. Cho nên, ta có thể đẩy những log này lên elastic search rồi từ đó dùng các công cụ thích hợp để phân tích.

READ MORE


Chạy Visual Studio Solution từ command line

Đôi khi ta muốn chạy một solution của Visual Studio từ command line thay vì phải mở Visual Studio IDE lên để giảm bớt tài nguyên cho hệ thống, ta có thể làm như sau:

  • Di chuyển đến thư mục chứa file .sln
  • Build code "C:\Program Files (x86)\MSBuild\14.0\Bin\msbuild.exe" SelfHost.sln /p:Configuration=Release (Hoặc là Debug)
  • Chạy file đã build SelfHost\bin\Release\SelfHost.exe

Để thuận tiện cho những lần chạy sau, ta có thể tạo một file bat, khi nào cần chỉ cần click một phát là xong.


Tôi học Machine Learning - 004 - Unsupervised Learning - Học không có giám sát

Bài ghi chú

Với học không có giám sát, chúng ta biết được một ít không không có ý tưởng về kết quả sẽ như thế nào. Chúng ta được đưa cho dữ liệu và yêu cầu trả về cấu trúc của dữ liệu đó dựa vào mối quan hệ giữa các biến trong dữ liệu.

Ví dụ:

  • Dựa vào dữ liệu về khách hàng của một công ty, chúng ta phân nhóm khách hàng để có thể thực hiện các chiến dịch bán hàng đặc biệt.
  • Phân loại các nhóm thành viên trên mạng xã hội.
  • Trong một bữa tiệc, ta có tập ghi âm thanh, ta có thể phân tích và tách các tạp âm để lọc ra âm thanh riêng của từng người.

Tôi học Machine Learning - 003 - Supervised Learning - Học có giám sát

Bài ghi chú

Với học có giám sát (Supervised Learning), chúng ta được đưa một dữ liệu với kết quả đầu ra tương ứng đã biết trước, ta cần xây dựng mối quan hệ dữa đầu vào và đầu ra, để dự đoán kết quả đầu ra của các giá trị đầu vào khác.

Ví dụ, dự đoán giá nhà dựa vào vị trí, kích thước của căn nhà.

Học có giám sát được chia ra làm hai loại, regression (hồi quy)classification (phân lớp).

  • Loại hồi quy: ta cố gắng dự đoán kết quả dưới dạng liên tục.
  • Loại phân lớp: ta cố gắng dự đoán kết quả dưới dạng rời rạc.

Ví dụ:

  • Loại hồi quy:
    • Cho kết quả kiểm tra đầu vào một lớp học, dự đoán số học sinh lên lớp.
    • Dựa vào kích thước, màu sắc của quả dưa leo, dự đoán giá bán sản phẩm.
  • Loại phân lớp:
    • Dựa vào kích thước, màu sắc của quả dưa leo, dự đoán có bán được hay không?
    • Cho thông tin khách hàng, dự đoán khách hàng mua sản phẩm hay không?

Tôi học Machine Learning - 002 - Khóa học trên Coursera

Hôm trước, mình đăng ký khóa học trên Udemy, sau khi coi các bài học đầu tiên thấy rằng nó chưa hợp với mình. Vì mình chưa biết gì về ML cả mà mới vào đã hướng dẫn ngay code rồi, càng coi càng rối.

Tìm trên Coursera (mình đã học một khóa về Python trên này), có một khóa về ML do Andrew ng hướng dẫn, anh này mình thấy rất nổi tiếng về lĩnh vực ML, cấu trúc khóa học cũng rõ ràng, bắt đầu từ cơ bản.

Nên mình quyết định dừng việc theo dõi khóa học trên Udemy và tập trung vào khóa học trên Coursera trước (https://www.coursera.org/learn/machine-learning). Mình có coi qua các đánh giá thì khóa này vẫn còn thiếu vài phần Wish the course also covered decision trees, random forests and boosting algorithms. mà mấy phần này bên Udemy có. Nên sau khi hoàn thành khóa trên Coursera mình sẽ quay lại coi bên Udemy.

Bạn nào mới bắt đầu tìm hiểu về ML thì có thể cùng mình học trên Coursera nhé. Có 2 tùy chọn Free hoặc trả phí (Trả phí thì sau khi hoàn thành sẽ có chứng nhận.)


Tôi học Machine Learning - 001 - Nhập môn

Machine Learning vẫn còn là một thứ mới mẻ và khiến mình tò mò, cho nên hôm nay mình đã bắt đầu tham gia một khóa học về nó. Chuỗi các bài “Tôi học Machine Learning” là những ghi chú của mình, chứ không phải là bài hướng dẫn, vì vậy có thể có những sai sót chủ quan trong nội dung bài viết. Nếu các bạn thấy chỗ nào sai, cứ thoải mái góp ý, điều đó sẽ rất có ý nghĩa với mình.

Phần mềm và ngôn ngữ

Đây là các phần mềm và ngôn ngữ mình cần phải cài đặt:

READ MORE


Cài đặt Nodejs trên Godaddy shared hosting

Năm ngoái, có người cần mình deploy code nodejs trên shared hosting của Godaddy, sau một hồi tìm kiếm thì mình kết luận không thể làm được. Sau đó mình đã deploy lên Heroku.

Ngày hôm nay, mình nhận được một tình huống tương tự như vậy, nhưng kết quả đã khác. Đã có thể cài nodejs lên shared hosting của Godaddy. Dưới đây là các bước thực hiện.

READ MORE


TeamCity – Build agent disconnected

Bellow is how I resolve my problem with TeamCity – Build agent disconnected.

TeamCity Agent Disconected

  • ssh to my centos agent machine.
  • Go to agent folder, in this case it is BuildAgent
  • I tried to stop the agent by bin/agent.sh stop but got no luck. When I started the agent it said that Build agent is already running with PID 1795, so that I could not restart it.
  • KILL the process by sudo kill 1795
  • Restart again bin/agent.sh start
    => It should work now.

Nodejs Module Caching

Nodejs Module Caching

Modules are cached after the first time they are loaded. This means (among other things) that every call to require(‘foo’) will get exactly the same object returned, if it would resolve to the same file.

Multiple calls to require(‘foo’) may not cause the module code to be executed multiple times. This is an important feature. With it, “partially done” objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.

If you want to have a module execute code multiple times, then export a function, and call that function.

(https://nodejs.org/api/modules.html#modules_caching)

READ MORE