Asked Mar 8th, 3:54 AM 150 0 3
  • 150 0 3
0

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

Share
  • 150 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 !!!

Vương Minh Thái @vuongthai95
Mar 8th, 4:05 AM

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
Nguyễn Duy Khánh @NDK1410
Mar 8th, 4:06 AM

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
Nguyễn Duy Khánh @NDK1410
Mar 8th, 4:07 AM

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

0
| Reply
Share
Vương Minh Thái @vuongthai95
Mar 12th, 12:40 AM

@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, 6:40 AM
+5

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
Answered Mar 8th, 6:28 AM
+3

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
Answered Mar 8th, 7:56 AM
+1

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