Toán tử so sánh trong JavaScript – w3seo phép toán compare

Rate this post

Tóm tắt: trong hướng dẫn này, bạn sẽ học cách sử dụng toán tử so sánh JavaScript để so sánh hai giá trị.

Các bài viết liên quan:

Giới thiệu về toán tử so sánh JavaScript

Để so sánh hai giá trị, bạn sử dụng các toán tử so sánh. Bảng sau minh họa các toán tử so sánh JavaScript:

Các toán tử so sánh

  • < nhỏ hơn
  • > lớn hơn
  • <= nhỏ hơn hoặc bằng
  • > = lớn hơn hoặc bằng
  • == bằng
  • ! = không bằng

Toán tử so sánh trả về một giá trị Boolean cho biết rằng phép so sánh là đúng hay không. Xem ví dụ sau:

let a = 10 > 5; // true
let b = 10 < 5; // false
let c = 5 == 5; // true

Toán tử so sánh nhận ít nhất hai giá trị (hoặc toán hạng). Nếu một trong hai giá trị có kiểu khác, JavaScript sẽ thực hiện chuyển đổi dựa trên các quy tắc cụ thể trước khi so sánh chúng. Chúng ta sẽ thảo luận chi tiết từng quy tắc trong các phần sau.

So sánh các con số

Nếu toán hạng là số, JavaScript sẽ thực hiện so sánh số. Ví dụ:

let a = 5, 
    b = 10; 
console.log(a >= b);  // false
console.log(b == 10); // true

Ví dụ này rất đơn giản. biến a là 5, b là 10. Biểu thức a> = b trả về false và biểu thức b == 10 trả về true.

So sánh các chuỗi

Nếu toán hạng là chuỗi, JavaScript sẽ so sánh các mã ký tự theo số từng cái một trong chuỗi.

let text1 = 'alice',
    text2 = 'bob';    
let compare = text1 < text2;
console.log(compare); // true
console.log(text1 == 'alice'); // true

Vì JavaScript so sánh các mã ký tự trong chuỗi theo số, bạn có thể nhận được một kết quả không mong muốn, ví dụ:

let f1 = 'alice',
    f2 = 'Bob';
let result = f2 < f1;
console.log(result); // true

Trong ví dụ này, f2 nhỏ hơn f1 vì chữ B có mã ký tự 66 trong khi chữ a có mã ký tự 97.

Để khắc phục điều này, trước tiên bạn phải chuyển đổi các chuỗi thành một định dạng chung, là chữ thường hoặc chữ hoa, sau đó thực hiện so sánh như sau:

let result2 = f2.toLowerCase() < f1.toLowerCase();
console.log(result2); // false

Lưu ý rằng toLowerCase () là một phương thức của đối tượng String tự chuyển đổi chuỗi thành chữ thường.

So sánh một số với một giá trị của một loại khác

Nếu một toán hạng là một số trong khi toán hạng kia thì không, JavaScript sẽ chuyển đổi toán hạng không phải số thành một số và thực hiện so sánh bằng số.

console.log(10 < '30'); // true

Trong ví dụ này, chuỗi ’30’ được chuyển đổi thành 30 và được so sánh với số 10. Dưới đây là một ví dụ:

console.log(10 == '10'); // true

Trong ví dụ này, JavaScript chuyển đổi chuỗi ’10’ thành số 10 và so sánh kết quả với số 10 cho kết quả là true.

So sánh một đối tượng với một phi đối tượng

Nếu một toán hạng là một đối tượng, JavaScript sẽ gọi phương thức valueOf () của đối tượng đó để lấy giá trị để so sánh. Nếu đối tượng không có phương thức valueOf (), thì JavaScript sẽ gọi phương thức toString () và sử dụng giá trị trả về để so sánh. Xem ví dụ sau:

let a = {
  valueOf: function() {
    return 10;
  }
};

let b = {
  toString: function() {
    return '15';
  }
};
console.log(a > 10); // false
console.log(b == 15); // true

Trong lần so sánh đầu tiên này, đối tượng apple có phương thức valueOf () trả về 10, do đó, JavaScript sử dụng 10 để so sánh. Trong lần so sánh thứ hai, JavaScript đầu tiên gọi phương thức valueOf (). Tuy nhiên, đối tượng màu cam không có phương thức valueOf () nên JavaScript gọi phương thức toString () để nhận giá trị trả về là 20.

So sánh Boolean với một giá trị khác

Nếu một toán hạng là Boolean, JavaScript sẽ chuyển nó thành một số và so sánh giá trị được chuyển đổi với toán hạng khác; true sẽ chuyển thành 1 và false sẽ chuyển thành 0.

alert(true > 0); // true
alert(false < 1); // true
alert(true > false); // true
alert(false > true); // false
alert(true >= true); // true
alert(true <= true); // true
alert(false <= false); // true
alert(false >= false); // true

Ngoài các quy tắc trên, các toán tử bằng (==) và không bằng (! =) Cũng có các quy tắc sau.

So sánh null và undefined

Trong JavaScript, null bằng không xác định. Nó có nghĩa là biểu thức sau trả về true.

alert(null == undefined); // true

So sánh NaN với các giá trị khác

Nếu một trong hai toán hạng là NaN, thì toán tử bằng (==) trả về false.

alert(NaN == 1); // false

Hay

alert(NaN == NaN); // false

Toán tử không bằng (! =) Trả về true khi so sánh NaN với một giá trị khác:

alert(NaN != 1); // true

Và ngoài ra

alert(NaN != NaN); // true

Bằng nhau nghiêm ngặt (===) và không bằng nhau nghiêm ngặt (! ==)

Bên cạnh các toán tử so sánh ở trên, JavaScript cung cấp các toán tử bằng không nghiêm ngặt (===) và không nghiêm ngặt bằng (! ==).

Ý nghĩa của nhà operator === bằng nghiêm ngặt, ! == không nghiêm ngặt bằng

Các toán tử băng nghiêm ngặt và không nghiêm ngặt hoạt động giống như toán tử bằng và không bằng ngoại trừ việc chúng không chuyển đổi toán hạng trước khi so sánh. Xem ví dụ sau:

alert("10" == 10); // true
alert("10" === 10); // false

Trong lần so sánh đầu tiên, vì chúng ta sử dụng toán tử bình đẳng, JavaScript chuyển đổi chuỗi thành số và thực hiện phép so sánh.

Tuy nhiên, trong phép so sánh thứ hai, chúng tôi sử dụng toán tử bình đẳng nghiêm ngặt (===), JavaScript không chuyển đổi chuỗi trước khi so sánh, do đó kết quả là sai.

Trong hướng dẫn này, bạn đã học cách sử dụng các toán tử so sánh JavaScript để so sánh các giá trị.

So sánh Object trong JavaScript

Thật đơn giản để so sánh các biến có giá trị primitive trong JavaScript. Chỉ cần sử dụng bất kỳ toán tử phương thức nào có sẵn, ví dụ: so sánh nghiêm ngặt:

'a' === 'c'; // => false
1   === 1;   // => true

Tuy nhiên, các Object thì khó so sánh hơn vì chúng dữ liệu tập hợp, gồm nhiều thuộc tính. Trong bài viết này, chúng ta sẽ học cách so sánh hai Object một cách chính xác trong JavaScript.

1. Tham chiếu

JavaScript cung cấp 3 cách để so sánh các giá trị:

  • Toán tử so sánh nghiêm ngặt ===
  • Toán tử so sánh không nghiêm ngặt ==
  • Hàm Object.is ()

Khi so sánh các Object bằng cách sử dụng bất kỳ phương pháp nào trên, kết quả true được trả về nếu tham chiếu vào một đối tượng. Đây là so sánh tham chiếu.

Chúng ta hãy xác định các Object hero1 và hero2 và xem sự so sánh tham chiếu trong thực tế:

const man1 = {
  name: 'Batman'
};
const man2 = {
  name: 'Batman'
};

man1 === man1; // => true
man1 === man2; // => false

man1 == man1; // => true
man1 == man2; // => false

Object.is(man1, man1); // => true
Object.is(man1, man2); // => false

man1 === man1 đánh giá là true vì cả hai toán hạng đều trỏ đến cùng một Object instance man1.

Mặt khác, man1 === man2 đánh giá là false vì toán hạng man1 và man2 là các trường hợp Object khác nhau.

Điều thú vị là các Object man1 và man2 có nội dung giống nhau: cả hai đều có một tên thuộc tính với giá trị ‘Batman’. Tuy nhiên, ngay cả khi so sánh các Object có cùng cấu trúc, hero1 === hero2 đánh giá là false.

so sánh tham chiếu hữu ích khi bạn muốn so sánh các tham chiếu Object, thay vì nội dung của chúng.

Nhưng trong hầu hết các tình huống, bạn cần so sánh nội dung thực tế của các Object: thuộc tính và giá trị của chúng. Hãy xem cách thực hiện điều đó.

2. So sánh thủ công

Cách rõ ràng để so sánh các Object theo nội dung là đọc các thuộc tính và so sánh chúng theo cách thủ công.

Ví dụ: hãy viết một hàm đặc biệt isHeroEqual () để so sánh 2 Object man:

function isManEqual(object1, object2) {
  return object1.name === object2.name;
}

const man1 = {
  name: 'Batman'
};
const man2 = {
  name: 'Batman'
};
const man3 = {
  name: 'Joker'
};

isHeroEqual(man1, man2); // => true
isHeroEqual(man1, man3); // => false

isManEqual () truy cập vào tên thuộc tính của cả hai Object và so sánh các giá trị của chúng.

Nếu các Object được so sánh có một vài thuộc tính, tôi thích viết các hàm so sánh như isManEqual (). Các chức năng như vậy có hiệu suất tốt – chỉ một số trình truy cập thuộc tính và toán tử so sánh tham gia vào quá trình so sánh.

So sánh thủ công yêu cầu trích xuất thủ công các thuộc tính – đối với các Object đơn giản, đó không phải là vấn đề. Nhưng để so sánh các Object lớn hơn (hoặc các Object có cấu trúc không xác định), so sánh thủ công sẽ không thuận tiện vì nó đòi hỏi nhiều mã mẫu soạn sẵn.

Hãy xem mức độ so sánh “key” của các Object có thể giúp ích như thế nào.

3. So sánh nông

Trong quá trình so sanh hai Object, chúng ta nhận được 1 danh sách các thuộc tính của object (sử dụng Object.keys ()), sau đó lần lượt kiểm tra các các giá trị này xem có bằng nhau không.

Dưới đây là cách triển khai khả thi của kiểm tra so sánh nông:

function shallowEqual(object1, object2) {
  const keys1 = Object.keys(object1);
  const keys2 = Object.keys(object2);

  if (keys1.length !== keys2.length) {
    return false;
  }

  for (let key of keys1) {
    if (object1[key] !== object2[key]) {
      return false;
    }
  }

  return true;
}

Bên trong hàm, các key1 và key2 là các mảng chứa các tên thuộc tính tương ứng của object1 và object2.

for cycle lặp qua các khóa và so sánh từng thuộc tính của object1 và object2 cho đẳng thức object1 [key]! == object2 [key].

Hãy sử dụng đẳng thức key để so sánh các Object có nhiều thuộc tính:

const man1 = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};
const man2 = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};
const man3 = {
  name: 'Joker'
};

shallowEqual(man1, man2); // => true
shallowEqual(man1, man3); // => false

shallowEqual(hero1, hero2) trả về true vì các Object hero1 và hero2 có cùng thuộc tính (name và realName) với cùng giá trị.

Mặt khác, shallowEqual(hero1, hero3) trả về false vì hero1 và hero3 có các thuộc tính khác nhau.

Nếu các giá trị thuộc tính của các Object để so sánh là các giá trị primitive, thì việc kiểm tra so sánh nông là cách tốt nhất.

Nhưng các Object trong JavaScript có thể được lồng vào nhau. Trong trường hợp như vậy, thật không may, sự so sánh nông cạn không hoạt động tốt.

Hãy thực hiện kiểm tra so sánh nông trên các Object có các Object lồng nhau:

const man1 = {
  name: 'Batman',
  address: {
    city: 'Gotham'
  }
};
const man2 = {
  name: 'Batman',
  address: {
    city: 'Gotham'
  }
};

shallowEqual(man1, man2); // => false

Lần này, ngay cả khi cả hero1 và man2 có cùng nội dung, thì shallowEqual (man1, man2) trả về false.

Các đối tượng lồng nhau hero1.address và hero2.address là các trường hợp đối tượng khác nhau. Do đó, so sanh coi rằng hero1.address và hero2.address là các giá trị khác nhau.

May mắn thay, So sánh sâu so sánh chính xác các đối tượng chứa các đối tượng khác. Hãy xem nó hoạt động như thế nào.

4. So sánh Sâu

So sánh sâu tương tự như so sánh nông, nhưng có một điểm khác biệt. Trong quá trình kiểm tra nông, nếu các thuộc tính được so sánh là các đối tượng, thì một kiểm tra bình đẳng nông đệ quy được thực hiện trên các đối tượng lồng nhau này.

Hãy xem việc triển khai kiểm tra bình đẳng sâu sắc:

function deepEqual(object1, object2) {
  const keys1 = Object.keys(object1);
  const keys2 = Object.keys(object2);

  if (keys1.length !== keys2.length) {
    return false;
  }

  for (const key of keys1) {
    const val1 = object1[key];
    const val2 = object2[key];
    const areObjects = isObject(val1) && isObject(val2);
    if (
      areObjects && !deepEqual(val1, val2) ||
      !areObjects && val1 !== val2
    ) {
      return false;
    }
  }

  return true;
}

function isObject(object) {
  return object != null && typeof object === 'object';
}

Dòng được đánh dấu areObjects &&! DeepEqual (val1, val2) chỉ ra rằng ngay sau khi các thuộc tính được so sánh là các đối tượng, một lệnh gọi đệ quy bắt đầu xác minh xem các đối tượng lồng vào nhau có bằng nhau hay không.

Bây giờ, hãy xem một ví dụ về deepEquality ():

const man1 = {
  name: 'Batman',
  address: {
    city: 'Gotham'
  }
};
const man2 = {
  name: 'Batman',
  address: {
    city: 'Gotham'
  }
};

deepEqual(man1, man2); // => true

Hàm bình đẳng sâu xác định một cách chính xác rằng hero1 và hero2 có cùng thuộc tính và giá trị, bao gồm sự bình đẳng của các đối tượng lồng nhau hero1.address và hero2.address.

Để so sánh sâu các đối tượng, tôi khuyên bạn nên sử dụng:

  • isDeepStrictEqual (object1, object2) của mô-đun sử dụng tích hợp Node
  • hoặc _.isEqual (object1, object2) của thư viện lodash.

5. Tóm tắt

Đẳng thức tham chiếu (sử dụng ===, == hoặc Object.is ()) xác định xem các toán hạng có phải là cùng một thể hiện đối tượng hay không.

Kiểm tra bình đẳng thủ công yêu cầu so sánh thủ công các giá trị của thuộc tính. Trong khi việc kiểm tra này yêu cầu viết bằng tay các thuộc tính để so sánh, tôi thấy cách tiếp cận này thuận tiện vì tính đơn giản của nó.

Khi các đối tượng được so sánh có nhiều thuộc tính hoặc cấu trúc của các đối tượng được xác định trong thời gian chạy, cách tiếp cận tốt hơn là sử dụng kiểm tra nông.

Cuối cùng, nếu các đối tượng được so sánh có các đối tượng lồng nhau, thì việc kiểm tra bình đẳng sâu là cách để thực hiện.

Hy vọng rằng bài viết của tôi đã giúp bạn hiểu chi tiết cụ thể của việc kiểm tra các đối tượng trong JavaScript.