Vietnam

    Nodejs.vn

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Tags
    • Groups
    • Search

    Điểm nhanh một vài giá trị đặc biệt trong Javascript

    Javacsript
    1
    1
    21
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • vananh.dao0809
      vananh.dao0809 last edited by vananh.dao0809

      Trong bài viết ngày hôm nay chúng ta cùng tìm hiểu về các giá trị đặc biệt trong Javascript nhé , Chúng ta cùng khám phá bài viết vô cùng thú vị này nhé .

      50-javascript.jpg
      1 Nonvalue

      Sự khác biệt giữa undefind và Null :

      • null được coi là object, và object đó thể hiện một giá trị rỗng.
      • undefined có nghĩa là chưa có giá trị nào hết .

      2 Sự đặc biệt của Undefined

      Khi chúng ta đang ở chế độ non-strict, Chúng ta có thể gán một giá trị cho undefined .Và tất nhiên điều này không được khuyến khích .
      Chúng ta có ví dụ sau :

      function foo() {
          undefined = 2; // realy bad idea~
      }
      
      foo();
      
      function foo() {
          "use strict";
          undefined = 2; // Type Error!
      }
      
      foo();
      

      Và trong cả chế độ strict và non-strict, ta đều có thể tạo biến local có tên là undefined. (facepalm) . ( Không khuyến khích làm điều này )

      function foo() {
          "use strict";
          var undefined = 2;
          console.log(undefined);
      }
      
      foo();
      

      3Toán tử Void

      Một cách đơn giản để chúng ta có thể lấy được giá trị undefined thay vì gọi trực tiếp undefined ra . Đó chính là sử dụng toán tử Void . Câu lệnh void ___ sẽ đưa tất cả giá trị đứng trước đi và trả lại undefined. Nó không thay đổi giá trị của toán hạng đứng trước nó, nó chỉ đơn thuần là đảm bảo không có một giá trị nào được trả ra sau lệnh đó.
      Chúng ta có ví dụ sau :

      var a = 22;
      console.log(void a, a); // undefined 22
      

      Việc sử dụng toán tử void này cũng hữu ích trong một số trường hợp, nếu ta cần chắc chắn rằng một câu lệnh nào đó không trả về giá trị. Ví dụ:

      function doSomething() {
          // note: `APP.ready` là biến mình tự tạo nhé
          if (!APP.ready) {
              // try again later
              return void setTimeout(doSomething, 100);
          }
          var result;
          // làm gì đó linh tinh để sinh kết quả
          return result;
      }
      
      // ta chưa thể thực hiện ngay bây giờ?
      if (doSomething()) {
          // thì đi xử lý task khác trước thôi
      }
      

      ** 4 NaN**

      NaN viết tắt là not a number , khi thực thi một bài toán bất kỳ mà một trong hai toán hạng không phải number (hoặc giá trị của nó không thể được thông dịch thành number ở dạng base 10 hoặc base 16), phép toán sẽ đưa về một kết quả fail nhưng vẫn thuộc kiểu number, và người ta gọi đó là giá trị NaN .
      Chúng ta có ví dụ :

      var a = 3 / "foo"; // NaN
      typeof a === "number"; // true
      

      NaN là một giá trị đặc biệt mà nó không thể so sánh bằng với một giá trị NaN nào khác (hay gọi là nó không thể bằng chính nó cũng được). Và đây là giá trị duy nhất không có tính reflexive (đặc tính duy nhất x === x). Vì thế nên NaN !== NaN,

      5 Infinity

      Infinity trong JS được định nghĩa Khi thực hiện chia cho 0 với dương ( âm ), kết quả trả về sẽ là Infinity ( -Infinity ) .

      Chúng ta có ví dụ sau :

      var a = 1 / 0; // Infinity
      var b = -1 / 0; // -Infinity
      

      JS sử dụng IEEE 754 floating-point để thể hiện số, do đó nó sẽ có hiện tượng overflow ngay cả với phép toán cộng và trừ, trong trường hợp ấy ta sẽ nhận được giá trị Infinity và -Infinity. Ví dụ:

      var a = Number.MAX_VALUE; // 1.7976931348623157e+308
      a + a;                    // Infinity
      a + Math.pow(2, 970);     // Infinity
      a + Math.pow(2, 969);     // 1.7976931348623157e+308
      

      Theo như đặc tả, nếu một phép toán như cộng trả về một giá trị quá lớn để có thể present, IEEE 754 sẽ "làm tròn về phía gần nhất" của giá trị. Vì thế nên, Number.MAX_VALUE + Math.pow(2, 969) gần Number.MAX_VALUE hơn so với Infinity, do đó nó làm tròn xuống, còn Number.MAX_VALUE + Math.pow(2, 970) gần hơn với Infinity thế nên là nó làm tròn lên. Nhưng mà thôi đừng nghĩ quá nhiều về cái vấn đề này làm gì đau đầu.

      Một khi overflow về một chiều nào đó của infinities, ta sẽ không thể quay lại được giá trị ban đầu. Hay nói cách khác, ta chỉ có thể đi từ hữu hạn tới vô hạn nhưng không thể đi từ vô hạn về hữu hạn.

      Nếu bạn còn nhớ một câu hỏi thời còn đi học: "Kết quả sẽ là gì khi một số vô hạn chia cho một số vô hạn?". Đầu óc ngây thơ của chúng ta có thể nghĩ là nó bằng 1 hoặc bằng "vô hạn". Cả hai đều sai, trong cả toán học và JS. Infinity / Infinity không được định nghĩa là một phép toán. Trong JS, kết quả trả về NaN.

      Nhưng nếu có một số dương hữu hạn nào đó chia cho Infinity?. Đơn giản thôi, 0. Và sẽ thế nào nếu một số âm hữu hạn chia cho Infinity? Mời đọc tiếp phần dưới.
      Zero
      Có thể điều này sẽ gây bối rối cho những người đọc với một cái đầu thuần toán học. nhưng JavaScript có cả số 0 bình thường (hay còn gọi là số 0 dương +0) và một số 0 âm -0. Trước khi ta đi giải thích tại sao -0 tồn tại, ta sẽ xem JS xử lý những thứ này như thế nào. Bên cạnh việc thể hiện dưới ký hiệu -0, số 0 âm còn là kết quả sinh ra từ một số phép toán.
      Ví dụ

      var a = 0 / -3; // -0
      var b = 0 * -3; // -0
      

      Phép cộng và trừ không thể sản sinh ra số 0 âm.
      Số 0 âm khi log trên developer console thường hiển thị -0, tuy nhiên một số browser cũ vẫn hiển thị 0. Mặc dù vậy, có một điều kì lạ là khi ta stringify một giá trị 0 âm, kết quả sẽ là "0".

      var a = 0 / -3;
      // một số browser vẫn hiển thị đúng
      a; // -0
      
      // cơ mà khi ta chuyển nó sang string thì lại sai
      a.toString();  // "0"
      a + "";        // "0"
      String(a);     // "0"
      
      // thậm chí là JSON
      JSON.stringify(a); // "0"
      

      Cơ mà được cái là nếu chuyển từ string sang number thì vẫn đúng:

      + "-0";           // -0
      Number("-0");     // -0
      JSON.parse("-0"); // -0
      

      Ngoài việc stringify đưa sai sự thật, thì ta cũng cần phải chú ý vì khi so sánh cũng có vấn đề:

      var a = 0;
      var b = 0 / -3;
      
      a == b;   // true
      -0 == 0;  // true
      
      a === b;  // true
      -0 === 0; // true
      
      0 > -0; // false
      a > b;  // false
      

      Rõ ràng với tất cả các tính chất trên, nếu như ta có ý định phân biệt -0 và 0 trong code, ta không thể nào chỉ dựa vào những cách so sánh thông thường, thay vào đó ta cần triển khai 1 hàm để kiểm tra:

      function isNegZero(n) {
          n = Number(n);
          return (n === 0) && (1 / n === -Infinity);
      }
      isNegZero(-0);      // true
      isNegZero(0 / -3);  // true
      isNegZero(0);       // false
      

      Còn bây giờ thì là câu hỏi tại sao chúng ta phải cần số 0 âm?
      Có một vào ứng dụng nhất định mà developer sử dụng độ lớn của số để thể hiện một phần thông tin (ví dụ như tốc độ chuyển động của animation frame) và dấu của số để thể hiện một phần thông tin khác (ví dụ như chiều của chuyển động).
      Trong những ứng dụng đó, nếu một biến dịch chuyển dần tới 0 và mất đi dấu của nó, ta sẽ mất đi một phần thông tin về hướng mà biến đó di chuyển tới 0. Giữ đúng dấu của số 0 sẽ ngăn việc tạo ra những mất mát thông tin không mong muốn.

      6 Special Equality

      Như ta có thể thấy ở các phần trên, giá trị NaN và giá trị -0 có những behaviour rất đặc biệt khi sử dụng trong so sánh bằng. NaN thì không bằng chính nó, còn -0 thì lại bằng với 0.
      Với ES6, có một hàm utility mới mà ta có thể sử dụng để kiểm tra tính bằng nhau của các giá trị đặc biệt này, mà không xảy ra bất kì exception nào. Hàm đó là Object.is(..):

      var a = 2 / "foo";
      var b = -3 * 0;
      
      
      Object.is(a, NaN);  // true
      Object.is(b, -0);   // true
      
      Object.is(b, 0);    // false
      

      Có một polyfill khá là đơn giản cho hàm này để sử dụng ở các môi trường pre-ES6:

      if (!Object.is) {
          Object.is = function(v1, v2) {
              // test for `-0`
              if (v1 === 0 && v2 === 0) {
                  return 1 / v1 === 1 / v2;
              }
              // test for `NaN`
              if (v1 !== v1) {
                  return v2 !== v2;
              }
              // everything else
              return v1 === v2;
          }
      }
      

      Không nên sử dụng Object.is(..) khi ta biết chắc rằng việc sử dụng == hoặc === đảm bảo an toàn. Việc sử dụng toán tử đem lại hiệu quả cao hơn và chắc chắn là thông dụng hơn. Object.is(..) phần lớn được sử dụng cho những trường hợp so sánh bằng đặc biệt.

      Tài liệu tham khảo : Viblo

      1 Reply Last reply Reply Quote 0
      • First post
        Last post