Polyfill: คืออะไร หลักการทำงาน และไลบรารีสำหรับจำลอง API

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-19 เวลาอ่าน: 9 นาที

Polyfill คือโค้ดที่จำลองฟังก์ชันการทำงานที่ขาดหายไป (API, เมธอด, อ็อบเจกต์) ในสภาพแวดล้อมที่ไม่ได้ถูกนำไปใช้แบบเนทีฟ Polyfill ช่วยให้คุณสามารถใช้คุณสมบัติสมัยใหม่ของ JavaScript, CSS หรือ Web API ในเบราว์เซอร์เก่าและรันไทม์ได้ ตาม MDN Web Docs โพลีฟิลล์เป็นเครื่องมือสำคัญสำหรับการปรับปรุงแบบต่อเนื่องและการรับประกันความเข้ากันได้ข้ามเบราว์เซอร์

ประเด็นสำคัญ

  • Polyfill คือการจำลองซอฟต์แวร์ของ API ที่ขาดหายไปในสภาพแวดล้อมรันไทม์ที่ไม่ได้ใช้งาน API นั้น
  • core-js คือไลบรารีโพลีฟิลล์มาตรฐานสำหรับ JavaScript สมัยใหม่ที่รองรับข้อเสนอ stage-4 ทั้งหมด
  • Polyfill.io คือบริการที่จัดเตรียมโพลีฟิลล์แบบไดนามิกเฉพาะสำหรับเบราว์เซอร์ของผู้ใช้
  • การทรานส์ไพล์ vs polyfill: การทรานส์ไพล์แปลงไวยากรณ์ (arrow function → function), polyfill เพิ่มเมธอดใหม่ (Array.includes, Promise)
  • การตรวจจับคุณสมบัติ (Feature detection) ตรวจสอบการมีอยู่ของการใช้งานเนทีฟก่อนโหลดโพลีฟิลล์เพื่อหลีกเลี่ยงความขัดแย้ง

Polyfill คืออะไร?

Polyfill คือส่วนของโค้ด (โดยปกติคือ JavaScript) ที่ใช้งานฟังก์ชันการทำงานที่สภาพแวดล้อมรันไทม์ไม่รองรับแบบเนทีฟ คำนี้ถูกคิดขึ้นโดย Remy Sharp ในปี 2009 เป็นการเล่นคำ: Polyfill เปรียบเสมือน Polyfilla ซึ่งเป็นผงสำหรับอุดรอยแตกบนผนัง Polyfill เติมเต็มช่องว่างระหว่างมาตรฐานและการรองรับในเบราว์เซอร์หรือรันไทม์เฉพาะ

Polyfill ไม่ได้แก้ไขโค้ดที่มีอยู่ —但它ขยายสภาพแวดล้อมรันไทม์ ถ้าเบราว์เซอร์ไม่รองรับ Array.prototype.includes โพลีฟิลล์จะเพิ่มเมธอดนี้ไปยังต้นแบบ Array ก่อนที่โค้ดหลักจะทำงาน โพลีฟิลล์สามารถจำลองอ็อบเจกต์ส่วนกลางใหม่ (Promise, Map, Set, Symbol), เมธอดสแตติก (Array.from, Object.assign) และเมธอดต้นแบบ

การตรวจจับคุณสมบัติ (Feature detection) เป็นกลไกบังคับก่อนติดตั้งโพลีฟิลล์ แทนที่จะตรวจสอบ user-agent (เบราว์เซอร์ใด) ควรตรวจสอบการมีอยู่ของเมธอด: if (!Array.prototype.includes) { Array.prototype.includes = ... } ซึ่งรับประกันว่าโพลีฟิลล์จะไม่เขียนทับการใช้งานเนทีฟถ้ามีอยู่แล้ว Google Analytics และบริการอื่นๆ รวบรวมข้อมูลการรองรับ API สำหรับการวิเคราะห์

เมื่อใดที่โพลีฟิลล์เกิดขึ้น

โพลีฟิลล์แรกเกิดขึ้นในยุค Internet Explorer 6–8 (2005–2009) เมื่อนักพัฒนาค้นพบช่องว่างระหว่างมาตรฐาน W3C และการใช้งานในเบราว์เซอร์ คำนี้ถูกนำเสนอโดย Remy Sharp ในปี 2009 ที่ BarCamp London โพลีฟิลล์มวลชนแรกคือ html5shiv (2009) — ไลบรารีที่เพิ่มการรองรับแท็ก HTML5 (<section>, <article>, <nav>) ใน Internet Explorer

ด้วยการมาถึงของ ES6 (2015) และวงจรการอัปเดต ECMAScript รายปี จำนวนโพลีฟิลล์ที่ต้องการเพิ่มขึ้น ทุกปีมาตรฐานเพิ่มเมธอดใหม่ (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) ที่เบราว์เซอร์เก่าไม่รองรับ core-js ซึ่งเริ่มต้นเป็น es6-shim ในปี 2014 กลายเป็นโซลูชันสากล ในปี 2026 core-js มีโมดูลโพลีฟิลล์มากกว่า 5,000 โมดูลสำหรับ ES5–ES2025

สิ่งที่สามารถและไม่สามารถทำโพลีฟิลล์ได้

หมวดหมู่สามารถทำโพลีฟิลล์ได้ไม่สามารถทำโพลีฟิลล์ได้
เมธอดต้นแบบArray.includes, String.startsWith
อ็อบเจกต์ส่วนกลางPromise, Map, Set, Symbol
เมธอดสแตติกObject.assign, Array.from
ไวยากรณ์ภาษาArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (ต้องการการรองรับเนทีฟ)

Polyfill vs การทรานส์ไพล์: ความแตกต่างและการทำงานร่วมกัน

การทรานส์ไพล์ แปลงไวยากรณ์ใหม่เป็นไวยากรณ์เก่า (const → var, () => {} → function() {}) Polyfill เพิ่มเมธอดและอ็อบเจกต์ที่ขาดหายไป (Promise, Array.includes) กลไกทั้งสองนี้เสริมซึ่งกันและกัน: การทรานส์ไพล์ทำให้โค้ดเข้ากันได้ทางไวยากรณ์ โพลีฟิลล์รับประกันความสมบูรณ์ของ API Babel + core-js เป็นการผสมผสานมาตรฐานสำหรับการรองรับที่สมบูรณ์

Babel @babel/preset-env พร้อมตัวเลือก useBuiltIns จะกำหนดว่าโพลีฟิลล์ใดจำเป็นตามเบราว์เซอร์เป้าหมาย useBuiltIns: "usage" วิเคราะห์ว่า API ใดถูกใช้ในโค้ดและนำเข้าเฉพาะโพลีฟิลล์ที่จำเป็นจาก core-js useBuiltIns: "entry" นำเข้าโพลีฟิลล์ทั้งหมดสำหรับเบราว์เซอร์เป้าหมายผ่านการนำเข้า core-js/stable เพียงครั้งเดียว

ตัวอย่าง: โพลีฟิลล์สำหรับ Array.prototype.includes

js
// การตรวจสอบการมีอยู่และการเพิ่มโพลีฟิลล์
if (typeof Array.prototype.includes !== "function") {
  Object.defineProperty(Array.prototype, "includes", {
    value: function(searchElement, fromIndex) {
      if (this == null) {
        throw new TypeError("Array.prototype.includes called on null or undefined");
      }
      var arr = Object(this);
      var len = arr.length >>> 0;
      if (len === 0) { return false; }
      var start = fromIndex | 0;
      var k = Math.max(start >= 0 ? start : len + start, 0);

      while (k < len) {
        if (arr[k] === searchElement) { return true; }
        k++;
      }
      return false;
    },
    writable: true,
    configurable: true,
  });
}

// การใช้งาน — ตอนนี้ปลอดภัยในทุกเบราว์เซอร์
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

โพลีฟิลล์ สำหรับ Array.prototype.includes ตรวจสอบว่าเมธอดถูกกำหนดบนต้นแบบ Array หรือไม่ ถ้าไม่ จะสร้างคุณสมบัติผ่าน Object.defineProperty ด้วยแฟล็ก writable: true, configurable: true การปฏิบัติตามข้อกำหนด ES2016: การตรวจสอบ null/undefined, การแปลงเป็นอ็อบเจกต์, การจัดการ fromIndex ที่เป็นลบ หลังจากเพิ่มโพลีฟิลล์แล้ว การเรียก arr.includes(3) จะทำงานในทุกเบราว์เซอร์ รวมถึง Internet Explorer 11

core-js: ไลบรารีโพลีฟิลล์มาตรฐาน

core-js เป็นไลบรารีโพลีฟิลล์ JavaScript ที่ครอบคลุมมากที่สุด รองรับข้อเสนอ stage-4 ทั้งหมดของ TC39 (มาตรฐาน ECMAScript) core-js มีโพลีฟิลล์สำหรับ Promise, Symbol, Map, Set, WeakMap, WeakSet, เมธอด Array, เมธอด String, เมธอด Object, เมธอด Number, เมธอด Math, Reflect, globalThis และข้อเสนอ stage-4 ทั้งหมด เวอร์ชันปัจจุบัน core-js 3.38+ ครอบคลุม ES5–ES2025

core-js ผสานรวมกับ Babel ผ่าน @babel/preset-env และตัวเลือก useBuiltIns หากไม่มีการผสานรวมนี้ นักพัฒนาจะต้องนำเข้าโพลีฟิลล์แต่ละตัวด้วยตนเอง: import "core-js/stable/array/includes" @babel/preset-env จะเพิ่มการนำเข้าที่จำเป็นโดยอัตโนมัติตามเบราว์เซอร์เป้าหมายจาก .browserslistrc ซึ่งช่วยลดขนาดบันเดิล — เฉพาะโพลีฟิลล์ที่จำเป็นเท่านั้นที่รวมอยู่

ตัวอย่าง: โพลีฟิลล์สำหรับ fetch

Fetch API เป็นหนึ่งใน Web API ที่ถูกทำโพลีฟิลล์บ่อยที่สุด การใช้งาน fetch แบบเนทีฟมีให้ใน Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015) แต่ไม่มีใน Internet Explorer และ WebView เก่า โพลีฟิลล์ whatwg-fetch จำลอง fetch ผ่าน XMLHttpRequest ทางเลือก — ใช้ isomorphic-fetch (โพลีฟิลล์สำหรับ Node.js และเบราว์เซอร์) หรือไลบรารีสากล axios ที่ไม่ต้องการโพลีฟิลล์

js
// โหลดโพลีฟิลล์ fetch สำหรับเบราว์เซอร์เก่าเท่านั้น
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// การใช้ fetch (ทำงานได้ทั้งกับโพลีฟิลล์และ API เนทีฟ)
async function loadData() {
  try {
    const response = await fetch("https://api.example.com/data");
    const json = await response.json();
    return json;
  } catch (error) {
    console.error("Failed to load:", error);
  }
}

การนำเข้าแบบไดนามิก ของโพลีฟิลล์ fetch ผ่าน import() รับประกันว่าเบราว์เซอร์สมัยใหม่จะไม่โหลดโค้ดที่ไม่จำเป็น โพลีฟิลล์โหลดแบบอะซิงโครนัสและไม่บล็อกเธรดหลัก หลังจากโหลด self.fetch จะแทนที่การใช้งานเนทีฟหรือเพิ่มการใช้งานที่ขาดหายไป นี่คือเทคนิคการปรับปรุงแบบต่อเนื่อง: เบราว์เซอร์สมัยใหม่ได้รับเฉพาะโค้ดเนทีฟ ส่วนเบราว์เซอร์เก่าได้รับโพลีฟิลล์เพิ่มเติม

การผสานรวม core-js กับ Babel

js
// babel.config.js — core-js + preset-env
module.exports = {
  presets: [
    ["@babel/preset-env", {
      useBuiltIns: "usage",
      corejs: {
        version: "3.38",
        proposals: true,
      },
      targets: {
        browsers: ["> 0.5%", "not dead", "not op_mini all"],
      },
    }],
  ],
};
none
# .browserslistrc — เบราว์เซอร์เป้าหมาย
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12

useBuiltIns: "usage" วิเคราะห์โค้ดและเพิ่มเฉพาะโพลีฟิลล์ที่ใช้งานจริง corejs.version ระบุเวอร์ชัน core-js ในโปรเจกต์ targets.browsers กำหนดระดับเบราว์เซอร์ขั้นต่ำ — ยิ่งเบราว์เซอร์เป้าหมายเก่าเท่าไหร่ โพลีฟิลล์ก็จะถูกรวมมากขึ้นเท่านั้น .browserslistrc ถูกใช้ไม่เพียงโดย Babel แต่ยังโดย Autoprefixer, PostCSS และ Stylelint สำหรับการกำหนดเป้าหมายที่สอดคล้องกัน

Polyfill.io และการโหลดโพลีฟิลล์แบบไดนามิก

Polyfill.io คือบริการ (และไลบรารีชื่อเดียวกัน) ที่กำหนดแบบไดนามิกว่าเบราว์เซอร์ของผู้ใช้ต้องการโพลีฟิลล์ใดและส่งคืนเฉพาะโพลีฟิลล์เหล่านั้น Polyfill.io ใช้ส่วนหัว User-Agent เพื่อกำหนดเวอร์ชันเบราว์เซอร์และให้ชุดโพลีฟิลล์ขั้นต่ำ ซึ่งช่วยลดปริมาณข้อมูลที่ส่งเมื่อเทียบกับบันเดิลโพลีฟิลล์สากล

การเชื่อมต่อ Polyfill.io ทำผ่านแท็ก <script> ก่อนโค้ดแอปพลิเคชันหลัก บริการวิเคราะห์ User-Agent และส่งคืนไฟล์ JavaScript ที่มีโพลีฟิลล์เฉพาะสำหรับเบราว์เซอร์นั้น Chrome จะไม่ได้รับโพลีฟิลล์ใดๆ IE 11 จะได้รับชุดที่สมบูรณ์ นี่เป็นแนวทางที่เหมาะสมที่สุดสำหรับประสิทธิภาพ: เบราว์เซอร์สมัยใหม่ไม่โหลดโค้ดที่ไม่จำเป็น

การเชื่อมต่อ Polyfill.io

html
<!-- Polyfill.io: การโหลดแบบไดนามิก -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>

<!-- เวอร์ชัน Polyfill.io ท้องถิ่น -->
<script src="/js/polyfill.js"></script>
<script>
  // feature detection for fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

พารามิเตอร์ features ใน URL ของ Polyfill.io ระบุว่าโพลีฟิลล์ใดที่จะโหลด ค่าที่เป็นไปได้: ชื่อเมธอด (Array.prototype.includes), อ็อบเจกต์ส่วนกลาง (Promise) หรือแฟล็ก (es6, es2016) แฟล็ก "default" โหลดชุดพื้นฐานสำหรับ JavaScript สมัยใหม่ สำหรับโปรเจกต์ที่ใช้งานจริง แนะนำให้โฮสต์ Polyfill.io บน CDN ของคุณเองหรือใช้เวอร์ชันท้องถิ่นของไลบรารีเพื่อควบคุมความพร้อมใช้งาน

โพลีฟิลล์ในแอปพลิเคชันมือถือและ WebView

WebView ในแอปพลิเคชันมือถือ (Android WebView, WKWebView บน iOS) เป็นสภาพแวดล้อมพิเศษสำหรับโพลีฟิลล์ เวอร์ชัน WebView ขึ้นอยู่กับเวอร์ชัน OS และการอัปเดต Chrome System WebView ที่ติดตั้ง (Android) หรือ WKWebView จาก iOS Safari ใน Android เวอร์ชันเก่า (4.4, 5.0) WebView จะใช้ Chromium 30–37 — โดยไม่รองรับ fetch, Promise, IntersectionObserver

React Native ใช้ JavaScriptCore (iOS) หรือ Hermes (Android) — เอนจินเหล่านี้ใช้งาน ES6+ แตกต่างกัน JavaScriptCore บน iOS รองรับคุณสมบัติ ES6 ส่วนใหญ่แต่อาจขาดข้อเสนอ stage-3 บางส่วน Hermes (ใช้โดยค่าเริ่มต้นใน React Native 0.70+) รองรับชุดจำกัดของมาตรฐาน ES — โพลีฟิลล์เป็นสิ่งจำเป็นสำหรับมัน

การตรวจสอบการรองรับใน WebView

js
// feature detection สำหรับ WebView
const polyfills = [];

// Promise
if (typeof Promise === "undefined") {
  polyfills.push("Promise");
}

// Fetch API
if (typeof self.fetch === "undefined") {
  polyfills.push("fetch");
}

// IntersectionObserver (จำเป็นสำหรับการโหลดแบบขี้เกียจ)
if (typeof IntersectionObserver === "undefined") {
  polyfills.push("IntersectionObserver");
}

// การโหลดโพลีฟิลล์แบบไดนามิก
if (polyfills.length > 0) {
  const script = document.createElement("script");
  script.src = "https://cdn.polyfill.io/v3/polyfill.min.js"
    + "?features=" + polyfills.join(",");
  document.head.appendChild(script);
}

การตรวจจับคุณสมบัติ สำหรับ WebView ตรวจสอบการมีอยู่ของ API ที่สำคัญ (Promise, fetch, IntersectionObserver) และโหลดโพลีฟิลล์แบบไดนามิกเฉพาะสำหรับ API ที่ขาดหายไป ซึ่งรับประกันว่า WebView สมัยใหม่ (Chrome 100+ บน Android 12) จะไม่โหลดโค้ดที่ไม่จำเป็น ในขณะที่ WebView เก่า (Android 5.0) ได้รับการรองรับที่จำเป็น

คำถามที่พบบ่อย

จำเป็นต้องใช้โพลีฟิลล์สำหรับ React Native หรือไม่?

React Native บน Hermes ต้องการโพลีฟิลล์สำหรับเมธอด ES บางส่วน: Array.flat, Array.flatMap, globalThis, TextEncoder แนะนำให้รวม core-js หรือ react-native-polyfill-globals สำหรับบิลด์ที่ใช้งานจริง JavaScriptCore บน iOS รองรับคุณสมบัติมากกว่า แต่อาจต้องการโพลีฟิลล์สำหรับข้อเสนอ stage-3 เช่นกัน

โพลีฟิลล์ส่งผลต่อประสิทธิภาพหรือไม่?

โพลีฟิลล์ ลดประสิทธิภาพลง 1–5% เนื่องจากการใช้งาน JavaScript ช้ากว่าการใช้งาน C++ แบบเนทีฟในเอนจิน ตัวอย่างเช่น โพลีฟิลล์ Promise ใน JS บริสุทธิ์ช้ากว่า Promise เนทีฟใน V8 อย่างไรก็ตาม สำหรับแอปพลิเคชันส่วนใหญ่ ความแตกต่างนั้นเล็กน้อย สำหรับโค้ดที่สำคัญ แนะนำให้ตรวจสอบการใช้งานเนทีฟผ่านการตรวจจับคุณสมบัติ

โพลีฟิลล์แตกต่างจากการทรานส์ไพล์อย่างไร?

การทรานส์ไพล์ แปลงไวยากรณ์: const → var, ฟังก์ชันลูกศร → function โพลีฟิลล์ เพิ่มอ็อบเจกต์/เมธอดใหม่: Promise, Array.includes, fetch การทรานส์ไพล์ทำงานในเวลาสร้าง โพลีฟิลล์โหลดในรันไทม์ กลไกทั้งสองจำเป็นสำหรับการรองรับโค้ดสมัยใหม่ในสภาพแวดล้อมเก่าอย่างสมบูรณ์

สามารถหลีกเลี่ยงโพลีฟิลล์ในปี 2026 ได้หรือไม่?

ได้ ถ้าผู้ชมเป้าหมายใช้เฉพาะเบราว์เซอร์สมัยใหม่ (Chrome 90+, Safari 15+, Firefox 90+) สำหรับโปรเจกต์ที่รองรับอุปกรณ์เก่าหรือผู้ใช้ในองค์กร (Internet Explorer 11 ยังคงใช้ในภาครัฐ) โพลีฟิลล์เป็นสิ่งจำเป็น วิเคราะห์สถิติเบราว์เซอร์ของผู้ชมของคุณผ่าน Google Analytics

ขนาดบันเดิลโพลีฟิลล์ core-js เท่าไหร่?

core-js ในบิลด์เต็มมีขนาด ~85 KB (gzip) เมื่อใช้ useBuiltIns: "usage" ใน Babel จะรวมเฉพาะโพลีฟิลล์ที่จำเป็น ซึ่งลดขนาดลงเหลือ 5–30 KB ขึ้นอยู่กับเบราว์เซอร์เป้าหมาย สำหรับเบราว์เซอร์สมัยใหม่ (Chrome 100+) อาจไม่จำเป็นต้องใช้โพลีฟิลล์ใดๆ เลย

สรุป

  • Polyfill คือการจำลอง API ที่ขาดหายไปในสภาพแวดล้อมรันไทม์ ทำให้โค้ดสมัยใหม่ทำงานร่วมกับสภาพแวดล้อมเก่าได้
  • core-js คือไลบรารีโพลีฟิลล์มาตรฐานสำหรับ ES5–ES2025 ผสานรวมกับ Babel ผ่าน @babel/preset-env
  • Polyfill.io คือบริการโหลดโพลีฟิลล์แบบไดนามิกตาม User-Agent ของเบราว์เซอร์
  • การทรานส์ไพล์ + โพลีฟิลล์ เป็นโซลูชันที่ครอบคลุม: Babel แปลงไวยากรณ์ core-js เพิ่ม API ที่ขาดหายไป
  • การตรวจจับคุณสมบัติ ตรวจสอบการใช้งานเนทีฟก่อนโหลดโพลีฟิลล์เพื่อประสิทธิภาพ
  • WebView และ Hermes ต้องการโพลีฟิลล์บังคับสำหรับ fetch, Promise และ IntersectionObserver ในเวอร์ชันเก่า

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม