Asked Mar 8th, 2019 3:54 a.m. 231 0 3
  • 231 0 3
0

Javascript's Closures - "I need your help, please !!!"

Share
  • 231 0 3

Heyyyyy xin chào các anh chị em, chào đại gia đình viblo.

Hôm nay 8/3, chúc các chị em luôn xinh đẹp và ngập tràn trong hạnh phúc, mong các anh em sẽ "ko quên" tặng những người phụ nữ của mình những đoá hoa tươi đẹp nhất, những món quà và những lời chúc đầy tình yêu thươngggg nha !

Giờ thì tới lượt chuyện của Khánh, hiện tại Khánh đang vừa học JS vừa làm một cái đồng hồ đếm ngược và đang khá bí, mời mọi người xem qua code rồi Khánh sẽ giải thích tiếp ạ

  countdown();
   
  function countdown() {
  var minutes = 20;
  var seconds = 1;

  seconds--;

   if (seconds < 10){
      seconds = "0" + seconds;
    }

   if (seconds != -1) {
      document.getElementById("timer").innerHTML = minutes + "&ensp;:&ensp;" + seconds;
      setTimeout("countdown()", 1000);a
    }

   if (seconds === -1) {
        minutes -= 1;
        if (minutes < 10){
          minutes = "0" + minutes;
        }
        seconds = 59;
      }

   if (minutes === "0" + "-1") {
      document.getElementById("timer").innerHTML = "Time Out !!!";
      document.getElementById("testform").submit();
    }
  }
 

Sẽ không có gì đáng nói nếu như đẩy 2 cái biến ở trên ra ngoài function cho nó thành global var, timer chạy ngon. Nhưng nếu là local var như ở trên thì theo như Khánh hiểu thì vòng đời của biến sẽ kết thúc sau khi function chạy xong, vì vậy cái timer nó sẽ chỉ đếm ngược duy nhất 1 lần và rồi nó dừng lại, tiếp tục tìm hiểu thì Khánh tìm ra được 1 giải pháp là dùng closure.

Nhưng mà trời ơi, mò mò được hơn nửa ngày rồi, đọc cũng vài bài tutorials rồi mà vẫn thấy mơ hồ ghê.... :-<

Khánh không mong muốn sẽ có ai đó đưa cho Khánh lời giải, Khánh chỉ mong mọi người có thể hướng dẫn cho Khánh cách dùng closure để giải quyết cái timer ở trên thôi. Xin cảm ơn mọi người rất rất nhiều !!!

Mar 8th, 2019 4:05 a.m.

Bạn có thể tham khảo phần Markdown Help (icon dấu ? ấy) để biết cú pháp viết bài cho dễ nhìn. Hiện tại câu hỏi đang hơi khó đọc!

Phần code thì cho vào

```ten-ngon-ngu

code

```

0
| Reply
Share
Mar 8th, 2019 4:06 a.m.

Xin lỗi những ai đã đọc bài, lần đầu mình viết nên k biết cách, gây ức chế thị lực cho mọi người nhưng mình đã sửa lại rồi ạ

0
| Reply
Share
Mar 8th, 2019 4:07 a.m.

@vuongthai95 cảm ơn bạn mình sửa lại rồi

0
| Reply
Share
Mar 12th, 2019 12:40 a.m.

@NDK1410 không có gì, mong rằng mọi người có thể giúp được bạn!

0
| Reply
Share

3 ANSWERS


Answered Mar 8th, 2019 6:40 a.m.
Accepted
+7

Góp ý đầu tiên của mình: Bạn đang viết code khá lộn xộn và tư duy lập trình chưa vững.

2019-03-08_12-29-35.jpg

Còn việc bạn không muốn dùng global var, theo mình hiểu là bạn chỉ khai báo 2 biến var đó tạm thời ra ngoài, khi nào dùng đến hàm countDown() thì mới tạo giá trị cho nó để đếm ngược (ví dụ bạn muốn đếm ngược 1 phút, hoặc 3 phút, tùy vào từng lúc gọi).

Vậy thì bạn cứ dùng global var như bình thường thôi, giá trị của biến Global sau khi dùng xong thì lại gán giá trị khác cho nó được và gọi sử dụng tiếp được mà bạn. Có vẻ bạn hiểu lầm Global var là không sửa được giá trị như Const var (hằng số const chỉ khai báo giá trị 1 lần và không được phép thay đổi giá trị).

Mình sẽ sửa lại hàm của bạn như sau:

//var minutes = 0;  //Bình thường khai báo global var sẽ cần viết riêng ra ngoài như thế này.
//var seconds = 0;  //Bình thường khai báo global var sẽ cần viết riêng ra ngoài như thế này.

Count10Minutes();

function Count10Minutes() {
  minutes = 10; //Nhưng chúng ta có thể bỏ chữ var đi, và biến minutes sẽ trở thành global cho dù được khai báo ở trong 1 hàm local
  seconds = 1; //Các biến khai báo và gán giá trị cho nó thành global thì có thể gọi được từ các hàm khác.
  countdown();
}

function countdown() {
  seconds--;
  if (minutes !== -1) {
    if (seconds !== -1) {
      console.log((minutes + "").padStart(2, '0') + " : " + (seconds + "").padStart(2, '0'));
      setTimeout(() => {
        countdown()}, 1000); bạn,
    } else {
      minutes--;
      seconds = 59;
      setTimeout(() => {
        countdown()}, 1000);
    }
  } else {
    console.log("Time Out !!!");
  }
}

Bạn có thể chạy thử online ở đây: https://playcode.io/263604?tabs=console&script.js&output

Share
Aug 13th, 2019 11:36 a.m.

Chào Tú, đã lâu không gặp rồi người anh em. Thật sự là buổi tối hôm đó mình đã giải quyết đc vấn đề, nên miss mất question này và giờ thì thời gian đã qua lâu quá. Ở cái đoạn truyền "0" + minutes mình viết là để nó hiển thị thời gian theo dạng 20:01 kiểu vậy đó, vì mình học JS theo kiểu mỳ ăn liền nên chắc chắn sẽ có kiến thức bị miss nhưng mình đảm bảo nó chạy được bạn à, k tin bạn chạy thử cái coi =]]

Ngày hôm nay mình quay lại đây, để gửi lời cảm ơn sâu sắc và cũng mong rằng bạn tha thứ cho mình, mình hiểu được cảm giác khi giúp đỡ một ai đó mà không nhận được lời cảm ơn thì cũng chả dễ chịu gì cả.

Bạn là một con người nhiệt tình và năng nổ. Mình đã đọc nhiều bài post của bạn, không chỉ chỉnh chu mà còn rất tâm huyết, you are so good mannnn !!!

Giữ sức khỏe, vững tinh thần và cố gắng thành công nhé người anh em, thank u so much.

+1
| Reply
Share
Answered Mar 8th, 2019 6:28 a.m.
+4

về closure thì mình thấy bài này viết khá rõ ràng: https://viblo.asia/p/ban-nen-biet-closure-hoat-dong-nhu-the-nao-aWj53VQQl6m sau khi sử dụng closure thì đại khái đoạn code nó sẽ như ở dưới, mình có sửa lại đôi chút cho dễ nhìn

timer();
function timer(){
  var minutes = 20;
  var seconds = 1;
  countdown();
  function countdown() {
  seconds--;

   if (seconds != -1) {
      document.getElementById("timer").innerHTML = formater(minutes) + "&ensp;:&ensp;" + formater(seconds);
    }
   
   if (seconds === -1) {
        minutes -= 1;
        seconds = 59;
      }

   if (minutes === -1) {
      document.getElementById("timer").innerHTML = "Time Out !!!";
         document.getElementById("testform").submit(); 
    } else {
      setTimeout(countdown, 1000, minutes, seconds);
    }
  }

  function formater(number){
    if(number < 10){
      return "0" + number;
    } else {
      return number;
    }
  }
}
Share
Aug 13th, 2019 11:36 a.m.

Chào Thủy, xin cảm ơn đường link và function formater của bạn. Những điều mình muốn nói thì đã có ở trên rồi, bạn chịu khó kéo lên trên xíu giúp mình nha ^_^ Cảm ơn bạn bằng tất cả sự tôn trọng, chúc bạn xinh đẹp và tuyệt vời hơn. You Are So Nice, Girl !!!

0
| Reply
Share
Answered Mar 8th, 2019 7:56 a.m.
+2

Bạn có thể tham khảo hàm này

var a = countdown();
a();
  function countdown() {
  var seconds = 5;

  return function(){

   if (seconds != -1) {
   		console.log(seconds)
        seconds--;
      	setTimeout("a()", 1000);
   }else{
   		console.log("time out")
   }

  }
}
Share
Aug 13th, 2019 11:37 a.m.

Hi Thức, cảm ơn bạn đã giúp mình. Mong rằng bạn sẽ bỏ qua cho sự comeback muộn màng của mình. Chúc bạn thành công nhé Bro.

0
| Reply
Share
Viblo
Let's register a Viblo Account to get more interesting posts.