Skip to content
This page is a draft. It may be incomplete or contain inaccuracies. If you have any comment, please feel free to leave some feedback!

ตัวดำเนินการทางตรรกศาสตร์

  • ในตอนนี้เราจะได้รู้จักกับตัวดำเนินการ ! && และ || ครับ

    ตัวดำเนินการสัญลักษณ์ลอจิกเกตสัญลักษณ์ทางคณิตศาสตร์
    ! (Logical NOT)
    && (Logical AND)
    || (Logical OR)
  • Logical NOT (!) (เปลี่ยนจาก true เป็น false, และจาก false เป็น true)

    x!x
    truefalse
    falsetrue
  • Logical AND (&&) จะมีค่าเป็นจริงก็ต่อเมื่อทั้งด้านซ้ายและด้านขวา มีค่าเป็นจริงทั้งคู่เท่านั้น

    aba && b
    truetruetrue
    truefalsefalse
    falsetruefalse
    falsefalsefalse
  • Logical OR (||) จะมีค่าเป็นจริงก็ต่อเมื่อ ด้านซ้าย หรือ ด้านขวา มีค่าเป็นจริงอย่างน้อยหนึ่งด้าน

    aba || b
    truetruetrue
    truefalsetrue
    falsetruetrue
    falsefalsefalse

ตัวอย่างการนำตัวดำเนินการทางตรรกศาสตร์ไปใช้

  • ยกตัวอย่างแบบฟอร์มลงทะเบียน ฟอร์มเหล่านี้มักจะมีช่องให้ทำเครื่องหมาย (checkbox) เพื่อยอมรับเงื่อนไขการใช้งาน (Terms and Conditions) และนโยบายความเป็นส่วนตัว (Privacy Policy) โดยปุ่มลงทะเบียนจะเปิดใช้งาน ก็ต่อเมื่อทำเครื่องหมายถูกลงในทั้งสองช่องเท่านั้น:

    index.html

    ลองเล่นกับตัวอย่างข้างบนดู

    1. ตอนแรก ปุ่ม Sign Up จะไม่สามารถกดได้
    2. ลองทำเครื่องหมายในช่อง Terms and Conditions และ Privacy Policy ดู → ปุ่ม Sign Up จะเปิดให้ใช้งานได้เมื่อทั้งสองช่องถูกติ๊กเท่านั้น
    3. กดปุ่ม Sign Up ดู → จะมีข้อความแสดงขึ้นมา
    4. ลองเอาเครื่องหมายออกจากช่องใดช่องหนึ่งดู → ปุ่ม Sign Up จะไม่สามารถกดได้
  • เริ่มจากโค้ดตั้งต้นนี้:

    html
    <p>
      <input id="acceptTerms" type="checkbox" />
      <label for="acceptTerms">I agree to the Terms and Conditions</label>
    </p>
    <p>
      <input id="acceptPrivacyPolicy" type="checkbox" />
      <label for="acceptPrivacyPolicy">I agree to the Privacy Policy</label>
    </p>
    <p>
      <input disabled type="button" id="signUpButton" value="Sign Up" />
    </p>
    
    <script>
      let acceptTerms = document.getElementById('acceptTerms')
      let acceptPrivacyPolicy = document.getElementById('acceptPrivacyPolicy')
      let signUpButton = document.getElementById('signUpButton')
    
      acceptTerms.onchange = () => {
        // เดี๋ยวมาเขียน
      }
      acceptPrivacyPolicy.onchange = () => {
        // เดี๋ยวมาเขียน
      }
      signUpButton.onclick = () => {
        alert('Sign up button clicked!')
      }
    </script>
  • ในโค้ดนี้ จะมีโค้ด HTML บางอย่างที่เราอาจไม่เคยเจอ

    • อย่างแรกคือ <input type="checkbox"> เป็นอินพุตชนิดหนึ่งที่ผู้ใช้งานเลือกทำเครื่องหมายได้ ว่าจะติ๊กหรือไม่ติ๊ก

    • อย่างที่สองคือ <label for="id"> หน้าที่ของมันคือ ทำให้ผู้ใช้งานสามารถคลิกที่ข้อความที่อยู่ข้างใน label แทนการคลิกที่อินพุตได้

    • อย่างที่สามคือ attribute disabled ทำให้ element นั้นไม่สามารถใช้งานได้ จะเห็นว่าถ้าปุ่มถูก disabled อยู่ เวลาคลิกจะไม่มีอะไรเกิดขึ้นเลย

  • ส่วนของ JavaScript จะมีเรื่องที่ควรรู้เพิ่มเติมคือ

    • ชื่ออินพุต.checked เอาไว้ตรวจสอบว่า อินพุตนั้นถูกติ๊กหรือไม่

      TIP

      ลองสั่ง acceptTerms.checked กับ acceptPrivacyPolicy.checked ในคอนโซลดูครับ

    • ชื่ออินพุต.onchange = () => { /* โค้ด */ } เอาไว้ใส่โค้ดที่ต้องการให้ทำ เมื่ออินพุตนั้นถูกเปลี่ยนค่า

      TIP

      ลองใส่ console.log ลงในโค้ด แล้วทดสอบดู จะเห็นว่าเมื่อติ๊กหรือเอาติ๊กออก ก็จะมีข้อความแสดงในคอนโซล

      js
      acceptTerms.onchange = () => {
        console.log('A')
      }
      acceptPrivacyPolicy.onchange = () => {
        console.log('B')
      }

ลองทำด้วยความรู้ตอนนี้

  • เราจะลองใช้ความรู้ที่เราเรียนไปก่อนหน้านี้ มาทำแบบฟอร์มลงทะเบียนให้เปิดใช้งานปุ่ม Sign Up กัน โดยจะยังไม่ใช้ตัวดำเนินการทางตรรกศาสตร์ สามารถเขียนโค้ดได้แบบนี้:

    js
    acceptTerms.onchange = () => {
      if (acceptTerms.checked) {
        if (acceptPrivacyPolicy.checked) {
          signUpButton.disabled = false
        } else {
          signUpButton.disabled = true
        }
      } else {
        signUpButton.disabled = true
      }
    }
    acceptPrivacyPolicy.onchange = () => {
      if (acceptTerms.checked) {
        if (acceptPrivacyPolicy.checked) {
          signUpButton.disabled = false
        } else {
          signUpButton.disabled = true
        }
      } else {
        signUpButton.disabled = true
      }
    }

    หมายเหตุ

    โค้ดข้างใน acceptTerms.onchange กับ acceptPrivacyPolicy.onchange นั้นเหมือนกัน เพราะเมื่อใดก็ตามที่เราติ๊กถูกหรือเอาติ๊กถูกออกจากกล่องอินพุตอันใดอันหนึ่ง เราต้องการตรวจสอบสถานะของอินพุตทั้งสองอันเสมอ

  • จะเห็นว่า โค้ดนี้ค่อนข้างยาว เดี๋ยวเราจะแก้ให้ดีขึ้นกว่านี้

ใช้ && เพื่อรวมเงื่อนไขเข้าด้วยกัน

  • เราสามารถนำตัวดำเนินการทางตรรกศาสตร์มาใช้ เพื่อรวมเงื่อนไขทั้งสองเข้าด้วยกัน และทำให้โค้ดสั้นลงได้

    js
    acceptTerms.onchange = () => {
      if (acceptTerms.checked && acceptPrivacyPolicy.checked) {
        signUpButton.disabled = false
      } else {
        signUpButton.disabled = true
      }
    }
    acceptPrivacyPolicy.onchange = () => {
      if (acceptTerms.checked && acceptPrivacyPolicy.checked) {
        signUpButton.disabled = false
      } else {
        signUpButton.disabled = true
      }
    }

ใช้ ! เพื่อกลับเงื่อนไข และจัดรูปให้โค้ดสั้นลงอีก

  • กรณีที่โค้ดอยู่ในรูปแบบนี้:

    js
    if (x) {
      y = true
    } else {
      y = false
    }

    สามารถเขียนให้สั้นลงได้เป็น:

    js
    y = x

    ทำไมถึงเขียนให้สั้นลงได้?

    ในกรณีที่ x เป็นข้อมูลชนิด boolean จะเห็นพบว่า:

    • ในกรณีที่ x เป็นจริง เราสามารถแทนที่ y = true ด้วย y = x ได้ เพราะว่า x มีค่าเป็น true อยู่แล้ว:

      js
      if (x) {
        y = true
        y = x // เพราะว่าในบล็อกนี้ x มีค่าเป็น true
      } else {
        y = false
      }
    • ในกรณีที่ x เป็นเท็จ เราสามารถแทนที่ y = false ด้วย y = x ได้ เพราะว่า x มีค่าเป็น false อยู่แล้ว:

      js
      if (x) {
        y = x // เพราะว่าในบล็อกนี้ x มีค่าเป็น true
      } else {
        y = false
        y = x // เพราะว่าในบล็อกนี้ x มีค่าเป็น false
      }
    • เราจะพบว่า ไม่ว่า x จะเป็นจริงหรือเท็จ สิ่งที่จะเกิดขึ้นตามมา เหมือนกันทั้งสองกรณี นั่นก็คือ y = x เราจึงสามารถเอาเงื่อนไขออกได้เลย

      js
      y = x
  • และด้วยเหตุผลเดียวกัน กรณีที่โค้ดอยู่ในรูปแบบนี้:

    js
    if (x) {
      y = false
    } else {
      y = true
    }

    สามารถเขียนให้สั้นลงได้เป็น:

    js
    y = !x

    ทำไมถึงเขียนให้สั้นลงได้?

    เนื่องจาก false คือ !true (เท็จ คือ ไม่จริง) และ true คือ !false (จริง คือ ไม่เท็จ)…

    • โค้ดของเราจึงสามารถเขียนเป็นแบบนี้ได้:

      js
      if (x) {
        y = false
        y = !true
      } else {
        y = true
        y = !false
      }
    • และด้วยเหตุผลเดียวกันกับตัวอย่างก่อนหน้า เราสามารถแปลงโค้ดเป็นแบบนี้:

      js
      if (x) {
        y = !true
        y = !x // เพราะว่าในบล็อกนี้ x มีค่าเป็น true, !x มีค่าเป็น false
      } else {
        y = !false
        y = !x // เพราะว่าในบล็อกนี้ x มีค่าเป็น false, !x มีค่าเป็น true
      }
    • และสุดท้ายก็ย่อเป็น:

      js
      y = !x
  • เนื่องจากโค้ดของโปรแกรมเราอยู่ในรูปแบบหลัง เราจึงสามารถย่อโค้ดให้สั้นลงได้อีกแบบนี้:

    js
    acceptTerms.onchange = () => {
      signUpButton.disabled = !(acceptTerms.checked && acceptPrivacyPolicy.checked)
    }
    acceptPrivacyPolicy.onchange = () => {
      signUpButton.disabled = !(acceptTerms.checked && acceptPrivacyPolicy.checked)
    }

    อย่าลืมเครื่องหมายวงเล็บ

    ในบรรทัดที่ 2 และ 5 ของโค้ดข้างต้น จะเห็นว่ามีเครื่องหมายวงเล็บครอบอยู่ ซึ่งเป็นเพราะว่า ตัวดำเนินการ ! มีความสำคัญมากกว่า && ดังนั้นเราจึงต้องใส่วงเล็บเข้าไป เพราะหากไม่ใส่วงเล็บ คอมพิวเตอร์จะจัดกลุ่มโค้ดของเราแบบนี้: (!acceptTerms.checked) && acceptPrivacyPolicy.checked ซึ่งไม่ใช่ที่เราต้องการ

ใช้ De Morgan's law เพื่อกลับเงื่อนไข

  • กฏของ De Morgan เป็นกฎในวิชาตรรกศาสตร์ที่ระบุไว้ว่า[1]

    และ

  • ซึ่งแปลเป็นภาษา JavaScript ได้ดังนี้:

    โค้ดนี้……มีความหมายเหมือนกับโค้ดนี้
    !(p && q)!p || !q
    !(p || q)!p && !q
  • เราสามารถนำกฏของ De Morgan มาใช้กับโค้ดของเราได้แบบนี้:

    js
    acceptTerms.onchange = () => {
      signUpButton.disabled = !acceptTerms.checked || !acceptPrivacyPolicy.checked
    }
    acceptPrivacyPolicy.onchange = () => {
      signUpButton.disabled = !acceptTerms.checked || !acceptPrivacyPolicy.checked
    }

สรุป

  • ในบทนี้เราได้นำตัวดำเนินการทางตรรกศาสตร์ต่าง มาใช้งาน เพื่อรวมเงื่อนไขหลาย เงื่อนไขเข้าด้วยกัน เพื่อทำให้โค้ดของเราสั้นลงได้

  • แต่จะเห็นว่าตอนนี้ โค้ดภายใน acceptTerms.onchange กับ acceptPrivacyPolicy.onchange นั้นเหมือนกันเลย เพื่อให้อินพุตทั้งสองอันทำงานเหมือนกัน เราจึงเขียนโค้ดที่ซ้ำซ้อนกันขึ้นมา (duplicate code) แต่ในบทต่อไป เราจะเรียนรู้การสร้างฟังก์ชัน เพื่อทำให้โค้ดที่ซ้ำซ้อนนี้หายไปได้

    js
    let recheckSignUpButton = () => {
      signUpButton.disabled = !acceptTerms.checked || !acceptPrivacyPolicy.checked
    }
    acceptTerms.onchange = () => {
      recheckSignUpButton()
    }
    acceptPrivacyPolicy.onchange = () => {
      recheckSignUpButton()
    }

  1. ในภาษาอังกฤษ กฏนี้ระบุไว้ว่า "The negation of a conjunction is the disjunction of the negations" และ "The negation of a disjunction is the conjunction of the negations" โดยที่ conjunction หมายถึง &&, disjunction หมายถึง ||, และ negation หมายถึง ! ↩︎