Javascript: promise, closure,... Kiến thức nâng cao nhưng không phải ai cũng hiểu rõ!

Tât nhiên là kiến thức trên là mình đã tìm hiểu trước nhưng không hiểu rõ nên mới đăng lên diễn đàn, mong mọi người bớt chút thời gian ghé qua để ae cùng hiểu rõ hơn.
Hôm nay mình muốn mở topic này để mong anh em có thể giải đáp và correct lại những lỗi logic mình còn nhầm lẫn về các kiến thức dưới .

  1. Promise
  2. Event loop
  3. Closure
  4. Curry
  5. Scope/Context
  6. Memoization

Theo mình hiểu như sau :
Promise : được sinh ra để xử lý bất đồng bộ và tránh callback hell . Tạo promise sẽ có nhiệm vụ trả về resolve hoặc reject. Instance của promise sẽ có function .then(callback(success , error )); .Câu hỏi của mình đặt ra là những object nào trong JS được thừa kế, có sẵn promise, và nếu có callback hell thì chắc cũng sẽ có promise hell đúng không ,nên dùng promise ES5 và ES6?

Event loop : Mình hiều cái này là bắt sự kiện trong js. nhưng thực sự không hiểu rõ, và không biết áp dụng thực tế như nào , phần này mong sẽ được giải đáp

Closure : Mình hiểu đại khái nó là sử dụng phương pháp dùng biến của thằng cha ,

function A(x){
    function B(y){
        function C(z){
            // C can be use x and y 
        }
    }
}

Curry: mình không chắc curry có phải chính xác là closure hay không nhưng đọc tài liệu thì mình có thấy phần này .

function A(x){ 
    function B(y){alert(x+y)};
}

VD :

var test = A(2);  // bien nay la x
test(6);  // bien nay la y.

Scope/Context : scope cuả js là block kiểu như giới hạn của nó là trong {} mà nó được tạo ra. Khái niệm context là gì thì mình vẫn chưa rõ @@

Memoization : last one , phần này đọc trong tài liệu nó có nói qua, không biết nó có quan trọng và hay được sử dụng không. Hay là chỉ khi cần nghiên cứu và tối ưu mới cần ?

Mình không hi vọng sẽ được giải đáp tất cả nhưng mình mong các bạn sẽ giải đáp phần promise eventloop và closure cho mình, vì mình thiết nghĩ 3 phần đó hay được sử dụng cần nắm kĩ .
Cảm ơn các pro đã bớt chút thời gian lướt qua :smiley:

1 Like

Mình chỉ biết Closure nên chia sẽ với bạn bằng ví dụ trên W3schools.com như vầy:
Trước hết, nói sơ về dòng đời của biến:

Biến toàn cục (Global variables): có dòng đời (lifetime) cho đến khi tắt Website đó thì nó sẽ chết.

Biến cục bộ (Local variables): có dòng đời ngắn, nó chỉ hoạt động trong FUNCTION khi triển khai và chết khi hàm đó thực hiện xong nhiệm vụ.

Ví dụ về cách cộng biến toàn cục thông qua hàm:

var counter = 0;

function add() {
    counter += 1;
}

add();
add();
add();

// the counter is now equal to 3

Biến counter (Global) chỉ nên thay đổi giá trị khi gọi hàm add() .

Vấn đề xảy ra khi có một câu lệnh nào khác đều có thể thay đổi giá trị biến counter, mà không cần gọi hàm add() .

Giải pháp là nếu bạn khai báo biến counter bên trong hàm add() ,thì không có câu lệnh bên ngoài nào có thể thay đổi nó mà không gọi đến hàm add() :

function add() {
    var counter = 0;
    counter += 1;
}

add();
add();
add();

// the counter should now be 3, but it does not work !

Nó không như mong đợi! Mỗi lần gọi hàm add() , biến counter đều trả về giá trị 1.
Tạo một hàm con bên trong hàm cha có thể giải quyết vấn đề này!

Hàm con trên người ta gọi là JavaScript Nested Functions

JavaScript hỗ trợ các hàm liền kề. Có nghĩa là các hàm con đều có thể sử dụng các biến toàn cục của hàm cha.

Trong ví dụ này, hàm con plus() có thể sử dụng biến counter trong hàm cha:

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}

Đều này đã giải quyết được tình trạng khó xử đối với biến counter, khi cúng ta gọi đến hàm plus() từ bên ngoài.

Chúng ta cũng cần tìm cách để đặt giá trị cho biến counter = 0 một lần duy nhất (có nghĩa làm giảm bớt tiến trình xử lý - đều này được ưu tiên hàng đầu trong viết ứng dụng bằng Javascript).

Chúng ta cần một closure.

JavaScript Closures : tạm hiểu là hàm được đóng kín tránh bị rò rỉ tài nguyên
Liệu nó có nhớ các giá trị tự triển khai không? Nó dùng để làm gì?

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

// the counter is now 3

Giải thích ví dụ trên:
Biến add được trả về giá trị bởi chính hàm triển khai chính nó ( hàm đó gọi là self-invoking function ).

Hàm tự triển khai chỉ chạy một lần duy nhất. Nó đặt giá trị cho biến counter bằng (0), và trả về một biểu thức hàm.

Bằng cách trên biến add trở thành một hàm. Phần tuyệt vời này chính là nó có thể sử dụng biến counter trong tầm vực của cha nó.

Và nó được gọi là JavaScript closure. Nhờ nó mà một hàm có khả năng đóng gọi các biến riêng tư (“private variables”).

Biến counter được bảo vệ trong tầm vực của bất cứ hàm nào, và chỉ có thể bị thay đổi bởi hàm add.


**

Một closure chính là một hàm có khả năng sử dụng tài nguyên trong tầm vực, kể cả khi hàm cha đã đóng.

**

HẾT

1 Like

Bạn nên trích dẫn lại các khái niệm, sau đó bôi đậm chỗ k hiểu.
Hoặc lấy ví dụ trực tiếp đoạn code bạn đang nhìn mà k hiểu, giải thích qua đoạn code làm gì (chỗ đã hiểu) rồi đến phần chưa hiểu thì nói tiếp chưa hiểu ở chỗ nào.
Ví dụ như Promise kia đọc đã thấy k đúng rồi, nó không trả về resolve hay reject, đọc tới đây là ngừng k muốn đọc tiếp vì thấy khái niệm còn chưa hiểu đúng, thì chỉ có đọc lại khái niệm thôi.

Toàn bộ cái bạn muốn đều có thể được tìm thấy trong You don’t know JS. Có 6 phần theo mình nhớ, đọc lại lần nữa xem.

3 Likes

Mình góp ý thế này, bạn giải thích nghe có vẻ đùng nhưng thật sự mình cứ thấy nó sai sai ấy, kiểu về cơ bản là đúng nhưng thực sự là bạn chưa hiểu một cách chính xác và tường tận. Muốn hiểu rõ về Closure thì trước tiên cần hiểu khái niệm scope, lexical scope và execution context. mình có link này cho bạn tham khảo https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md. tác giả có tóm tắt lại một câu " Closure is when a function can remember and access its lexical scope even when it’s invoked outside its lexical scope."

2 Likes

thanks bạn, mình sẽ đọc qua quyển ý.

thank bạn . Quyển này giống với quyển You dont know JS của bạn lovemagic thì phải .

đây là bản chính thức của tác giả trên github với hơn 50k star và bạn

Thank bạn. Bạn còn tài liệu nào liên quan đến js k , mình xin luôn một thể vs

Cảm ơn bạn nhé. Giờ mình hiểu closure là gì rồi, cũng nhờ vậy mà nhớ luôn cả self-invoking function luôn.
Mình cứ đi tìm đâu xa trong khi w3school có . Hihi.

Cầu này rất đúng rồi! Cảm ơn bạn chia sẽ!

Mình toàn học trên W3schools.com à, mình thấy trên đó có đủ những thứ cần thiết nếu bạn nắm vững từng bài học: https://www.w3schools.com/js/default.asp
Còn để mở rộng và ứng dụng thực tế hơn bạn cần tự Viết ứng dụng nhiều bằng Javascript
Sẵn có trang kinh điển này cho bạn tham khảo: http://youmightnotneedjquery.com/

Chào mọi người, cho mình hỏi là, trong trường hợp trên bạn Kollein Vĩnh có kết hợp với cái self-invoking function , nên sau lần gọi đầu thì add trở thành 1 function, vậy còn cách nào để sử dụng closure hiệu quả, hoặc các bạn có thể cho mình thêm ứng dụng cụ thể mà closure làm được với, riêng mình thấy khả năng “nhớ” của nó là hay lắm rồi :smiley:

Bạn ơi cho mình hỏi một tý.

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();//1
add();//2
add();//3

Bạn có viết: “Hàm tự triển khai chỉ chạy một lần duy nhất”. Câu này có nghĩa là sao zậy bạn?
Mình chưa biết lý do tại sao mỗi lần gọi thì add() lại tăng thêm 1.

mình hiểu thế này:
khi khai báo thằng add, người ta khai báo 2 hàm lồng nhau, f2 nằm trong f1.
f2 trả về giá trị counter++
f1 khởi tạo biến counter và trả về hàm f2
lúc này giá trị của add là f1
khi chạy hàm add lần đầu, nó chạy f1 đồng thời thay đổi giá trị của chính nó thành f2 và giữ thêm 1 biến là counter.
các lần gọi hàm add tiếp theo tương đương với việc chạy f2, nên có thể nói f1 đã tự triển khai và chỉ chạy 1 lần duy nhất.

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?