รูปแบบ JavaScript ที่วุ่นวาย

รูปแบบ JavaScript ที่วุ่นวาย

ขึ้นอยู่กับว่าคุณถามใคร JavaScript เป็นหนึ่งในสิ่งต่อไปนี้:

  1. ภาษาที่มีเสน่ห์และแสดงออกด้วยนิสัยใจคอเล็กน้อย
  2. พฤติกรรมแย่ๆ แย่ๆ แย่ๆ แย่กว่าทุกครั้งที่ผ่านมา

วันนี้ เราจะมาอธิบายข้อโต้แย้งที่สองโดยให้ข้อมูลโค้ดบางส่วนที่สร้างขึ้นโดยมีวัตถุประสงค์เพื่อสร้างความสับสน ในขณะที่คุณแน่นอนสามารถเขียนวุ่นวาย JavaScript โดยไม่ต้องเทคนิคเหล่านี้ผมหวังว่าจะช่วยให้คุณมีชุดเครื่องมือขยายที่สามารถช่วยคุณโปรแกรมเมอร์ที่โปรดปรานแกงกับGhaunadar โบราณหนึ่งโกลาหล deified

แก้ไข: ฉันรู้ว่าฉันต้องชัดเจน 100% ไม่เคยทำสิ่งเหล่านี้

ปัญหาที่ 1: คีย์อ็อบเจ็กต์มีข้อ จำกัด เกินไป!

น่ารำคาญไหมที่ สตริงและสัญลักษณ์เท่านั้นที่สามารถเป็นกุญแจสำหรับวัตถุใน JavaScript ได้ เพื่อประโยชน์ที่ดี แม้แต่ Python ก็ช่วยให้เราสร้างดัชนีตาม tuples ได้เป็นอย่างน้อย! JavaScript จะถูกแทนที่โดย Python จริงหรือ

ตัวอย่างของปัญหาที่เห็นได้ชัดสามารถเห็นได้ด้านล่าง:

const cat = {
  variant: 'hunter',
  preferredPrey: 'anything',
}
const dog = {
  variant: 'sniffer',
  smellSkill: 'excellent'
}
const talk = {
  [cat]: 'meow',
  [dog]: 'woof'
};
console.log(talk[dog]); // "woof"
console.log(talk[cat]); // "woof", oh no!!!!

เราจะทำอะไรได้บ้าง? ไม่มีทางที่เราจะปรับปรุงสถานการณ์นี้ได้หรือไม่?

วิธีแก้ไข: Symbols + toPrimitive + Object.prototype

เราสามารถหลีกเลี่ยงข้อ จำกัด นี้ได้โดยเพียงแค่เขียนการเรียกtoPrimitiveของObjectใหม่เพื่อให้สร้างสัญลักษณ์ใหม่สำหรับทุกวัตถุ! วัตถุใดๆ เมื่อแปลงเป็นแบบดั้งเดิม จะเปลี่ยนเป็นสัญลักษณ์ใหม่ที่ชัดเจนซึ่งคุณสามารถสร้างดัชนีได้!

{
  // Make all objects indexable!!
  const id = Symbol('idkey')
  Object.prototype[Symbol.toPrimitive] = function(){
    if (!this[id]) {
      this[id] = Symbol('id');
    }
    return this[id];
  }
}
const cat = {
  variant: 'hunter',
  preferredPrey: 'anything',
}
const dog = {
  variant: 'sniffer',
  smellSkill: 'excellent'
}
const talk = {
  [cat]: 'meow',
  [dog]: 'woof'
};
console.log(talk[cat]); // "meow", hooray!!!
console.log(talk[dog]); // "woof"

สิ่งนี้ใช้ได้กับอ็อบเจ็กต์ อาร์เรย์ อินสแตนซ์ของคลาส แม้แต่คลาสเอง คุณตั้งชื่อมัน! เราได้แก้ไข JavaScript โดยใช้พลังของ JavaScript! JavaScript ยอดเยี่ยมหรือไม่?

(นอกจากนี้ โครงสร้างข้อมูล Map ของ JavaScript ยังอนุญาตให้ทำเช่นนี้ได้ หากคุณหวังว่าจะแก้ปัญหานี้ในลักษณะที่สมเหตุสมผล นั่นเกือบจะเป็นแนวทางที่แน่นอน!)

ปัญหาที่ 2: ฉันจบลงด้วยการพึ่งพาการปิดของฉันมากเกินไป!

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

 
function someFunction(a, b, c){
  doStuffTo(a);
  const z = a.blah.bleep(b);
  // This section operates solely on z
  // could be used elsewhere, but isn't yet.
  // ---
  z.doSomething();
  z.doAnotherThing();
  // ---
  return c.combineWith(z);
}

ปัญหาเดียวคือ ไม่มีอะไรขัดขวางเราจากการพึ่งพาaหรือbในส่วนนั้นโดยไม่ได้ตั้งใจ ซึ่งจะทำให้การแยกออกยากขึ้นในอนาคต แดงฉันหวังว่าฉันจะสามารถมั่นใจได้ว่าบล็อกมีการเข้าถึงzเท่านั้น แต่ยังเป็นส่วนหนึ่งของฟังก์ชั่น!

วิธีแก้ปัญหา: Nuke the Closure

การใช้ proxies + with() ทำให้เราสามารถทำโปรแกรม shenanigans กับ stack ได้ เราสามารถจำกัดการปิดเพื่อให้เข้าถึงได้เฉพาะสิ่งที่บล็อกสนใจเท่านั้น!

ตัวอย่างวิธีการทำงานของกลยุทธ์นี้แสดงไว้ด้านล่าง:

function only(definedItems){
  return new Proxy({}, {
    has(_, prop){
      return !definedItems.includes(prop);
    },
    get(_, prop){
      throw new Error("Referenced variable " + prop.toString() + " out of scope!");
    },
    set(_, prop){
      throw new Error("Referenced variable " + prop.toString() + " out of scope!");
    }
  });
}
const a = 'available';
const b = 'unavailable';
with (only['a', 'console']) {
  console.log(a); // "available"
  console.log(b); // Throws!!
}

หากเรามีส่วนย่อยของฟังก์ชันที่มีความหมายเฉพาะกับตัวแปรzเท่านั้น เราสามารถจำกัดการเข้าถึงตัวแปรเหล่านั้นและตัวแปรเหล่านั้นเพียงอย่างเดียว เพื่อให้แน่ใจว่าเราสามารถสรุปได้ในภายหลังหากเราต้องการใช้ซ้ำ ข้อมูลโค้ดข้างต้นจะกลายเป็น:

 
function someFunction(a, b, c){
  doStuffTo(a);
  const z = a.blah.bleep(b);
  with (only(['z'])) {
    z.doSomething();
    z.doAnotherThing();
  }
  return c.combineWith(z);
}

ปัญหาที่ 3: ฉันเกลียดเครื่องหมายคำพูด!

นี่คือความต่อเนื่องของเทคนิคข้างต้น โดยที่ proxy + with() ให้คุณเข้าถึงการปิดโดยโปรแกรมเพื่อแลกกับจิตวิญญาณของคุณ

สมมติว่าคุณพิมพ์foo [บาร์]เมื่อคุณหมายถึงการพิมพ์foo [ ‘บาร์’] ตอนนี้ JavaScript กำลังบอกคุณว่าแถบนั้นไม่ได้กำหนดแม้ว่าจะชัดเจนจริงๆ ว่าคุณต้องการพิมพ์อะไร ทำไมมันช่างอวดดีนัก พระเจ้า บางครั้งคอมพิวเตอร์ก็โง่

วิธีแก้ปัญหา: สายเปลือย

ห่อทุกไฟล์ในประโยค ol ขนาดใหญ่ด้วย () โดยใช้พร็อกซีเฉพาะเช่นด้านบน! ตอนนี้ตัวระบุที่ถูกต้องใดๆ ที่ไม่ได้กำหนดไว้เป็นอย่างอื่น ตอนนี้ก็เป็นสตริงที่ถูกต้องเช่นกัน!

const bareStrings = new Proxy({}, {
  has(_, prop){
    return window[prop] === undefined;
  },
  get(_, prop){
    return prop.toString();
  }
});
with(bareStrings){
  const foo = {
    bar: "baz"
  }
  console.log(foo[bar]); // Returns Baz
}

ปัญหาที่ 4: ผู้คนมักแสดงความคิดเห็นโค้ดของฉัน!

ลองนึกภาพสิ่งนี้: คุณได้เขียนฟังก์ชันหลักแล้ว จากนั้นมีคนอื่นเข้ามาใช้คุณและแสดงความคิดเห็นเป็นส่วนหนึ่งของการทดสอบหรืออะไรก็ตาม การเปลี่ยนแปลงนั้นถูกเพิ่ม ส่ง และผลักโดยไม่ได้ตั้งใจ ไซต์ทั้งหมดของคุณล่ม และพอร์ตการลงทุนของผู้ถือหุ้นของคุณลดลง 0.03% ภัยพิบัติที่สมบูรณ์

แน่นอน การทดสอบควรจับสิ่งนี้ และแน่นอนว่าสิ่งต่าง ๆ ควรผ่านการตรวจสอบโค้ดที่เข้มงวดกว่านี้ และแน่นอนว่าบางที linter อาจช่วยได้หรืออะไรก็ตาม แต่นี่คือโลกแห่งความจริงที่เรากำลังพูดถึง และโครงสร้างพื้นฐานคือความฝัน ปัญหารหัสควรแก้ไขด้วยรหัส

วิธีแก้ปัญหา: ไม่แสดงข้อคิดเห็น ()

เราสามารถใช้ประโยชน์จากพฤติกรรมที่ยอดเยี่ยมของ JavaScript ได้อีกครั้ง! การเรียกใช้ toString() บนฟังก์ชันจะคืนค่าแหล่งที่มาของฟังก์ชัน ซึ่งหมายความว่าเราสามารถกำหนดฟังก์ชันที่มีลำดับสูงกว่าที่ทำงานบนซอร์สโค้ดได้เอง! มหัศจรรย์!

 
function uncomment(fn){
  const body = fn.toString().replace(////, '');
  return new Function(`return (${body})(...arguments)`);
}
function fn(a){
  // return a + 1;
  return a
}
fn(1) // returns 1
uncomment(fn)(1) // returns 2!

แสดง JavaScript ที่วุ่นวายของคุณให้ฉันดู

ฉันต้องการเห็น JavaScript ที่คุณเก็บไว้ใต้พรม JavaScript ถูกฝังลึกลงไปใต้ดิน ไม่เคยถูกค้นพบด้วยมือมนุษย์ JavaScript พ่อของคุณเตือนคุณเกี่ยวกับ

ค้นพบพวกเขา

ฉันต้องมีพวกเขา

Evin Sellin เป็นวิศวกรซอฟต์แวร์และผู้จัดหาการเขียนโปรแกรมที่ไม่ดี เขานั่งอยู่บนเศษเล็กเศษน้อยที่น่าเกลียดเหมือนมังกรบนขุมสมบัติ แสวงหาสิ่งอื่นๆ อย่างต่อเนื่องเพื่อเพิ่มความน่าสะพรึงกลัวของเขา

Credit : https://evinsellin.medium.com/chaotic-javascript-patterns-1025a8f077e6

Leave a Comment

Your email address will not be published.