demo JS functions such as map(), reduce(), filter(), etc.
$ node index.js
- Sử dụng các hàm built-in cho Array của JavaScipt thay vì viết vòng lặp for
- Lợi ích:
- Sử dụng hàm built-in ngắn gọn, tên hàm xúc tích miêu tả sẵn mục đích của hàm
- Theo phong cách functional programming: mỗi hàm thực hiện 1 mục đích riêng biệt, nhận input và trả về output
- Hạn chế đc các side effects: ảnh hưởng đến dữ liệu gốc, thay đổi dữ liệu gốc ngoài ý muốn -> những side effects rất khó debug
// mảng data gốc
const data = [
{name: 'SP1', manufacturer: 'Apple', price: 500, sales: 20, status: 'old'},
{name: 'SP2', manufacturer: 'Apple', price: 1500, sales: 10, status: 'new'},
{name: 'SP3', manufacturer: 'Samsung', price: 500, sales: 10, status: 'old'},
{name: 'SP4', manufacturer: 'Samsung', price: 1500, sales: 20, status: 'new'},
{name: 'SP5', manufacturer: 'HTC', price: 1200, sales: 10, status: 'new'},
{name: 'SP6', manufacturer: 'Motorola', price: 4500, sales: 10, status: 'old'},
{name: 'SP7', manufacturer: 'Apple', price: 600, sales: 20, status: 'old'},
]
// 1 cách viết tạo side effect mà nhiều người hay mắc phải -> mảng data gốc bị thay đổi
let newArr = [];
for (let i = 0; i < data.length; i++) {
let item = data[i]; // gán item bằng 1 phần tử trong mảng data
item.price = item.price / 2; // thay đổi thuộc tính price của item -> data.price cũng thay đổi theo
newArr.push(item);
}
// sau khi chạy vòng lặp này, chúng ta có 1 mảng newArr với price bằng 1 nửa
// những chính mảng data gốc cũng đồng thời bị thay đổi dù đây không phải là chủ ý của chúng ta
// => đây chính là 1 side effect
- Tại sao data lại bị thay đổi: Quy tắc của JS: pass by value hay pass by reference
- JS luôn là pass by value, tuy nhiên khi gán arrays hay objects thì 'value' đc pass lại là 'reference' tới object hay mảng này
- Khi pass by value: thay đổi giá trị của biến đc gán sẽ không thay đổi giá trị gốc
- Ví dụ ở dưới trong hàm
changeObject(x)
khi thay giá trị của biếnx
với một object mới, giá trị của biếnx
ở ngoài không bị thay đổi, vì biếnx
bên trong hàm lúc này hoàn toàn trỏ đến 1 object mới - Tuy nhiên, khi thay đổi thuộc tính
member
thì cả biếnx
bên trong hàm và ngoài hàm đều bị thay đổi
function changeObject(x) {
x = {member:"bar"};
console.log("in changeObject: " + x.member);
}
function changeMember(x) {
x.member = "bar";
console.log("in changeMember: " + x.member);
}
var x = {member:"foo"};
console.log("before changeObject: " + x.member);
changeObject(x);
console.log("after changeObject: " + x.member); /* change did not persist */
console.log("before changeMember: " + x.member);
changeMember(x);
console.log("after changeMember: " + x.member); /* change persists */
- Kết quả:
before changeObject: foo
in changeObject: bar
after changeObject: foo
before changeMember: foo
in changeMember: bar
after changeMember: bar
obj.propertyName
: Khi dùng.
thì sẽ hiểu đấy là tên thuộc tính của object luônobj['property_name']
: Khi dùng[..]
thì bên trong phải là 1 chuỗi- Có thể truy vấn thuộc tính qua 1 biến, biến này lưu tên thuộc tính theo dạng chuỗi
let obj = {'product_name': 'IPhone'}
console.log(obj.product_name);
console.log(obj['product_name']);
let name2 = 'product_id';
obj.name2 = 'Samsung'; // dùng '.' thì name2 đc hiểu trực tiếp là tên thực của thuộc tính
obj[name2] = 'HTC'; // dùng [] thì truyền vào giá trị của biến name2 là 'product_id'
console.log(obj);
- Kết quả:
IPhone
IPhone
{ product_name: 'IPhone', name2: 'Samsung', product_id: 'HTC' }