วัตถุ HTMLScriptElement แทนแท็ก <script> ใน DOM ใช้สร้าง โหลด และจัดการสคริปต์ไดนามิก รวมถึงควบคุมการโหลดแบบ async/defer
การสร้าง script element
const script = document.createElement('script');
คุณสมบัติสำคัญของ Script Object
| คุณสมบัติ | คำอธิบาย | ประเภท |
|---|---|---|
src |
URL ของไฟล์สคริปต์ภายนอก | Read/Write |
type |
MIME type (default: "text/javascript") | Read/Write |
async |
โหลดแบบ asynchronous (ไม่บล็อก parsing) | Read/Write (Boolean) |
defer |
เลื่อนการรันจนกว่า HTML parsing จบ | Read/Write (Boolean) |
crossOrigin |
CORS setting: "anonymous", "use-credentials" | Read/Write |
text |
เนื้อหาสคริปต์ inline (text content) | Read/Write |
integrity |
Subresource Integrity hash | Read/Write |
referrerPolicy |
Referrer policy สำหรับ request | Read/Write |
noModule |
ไม่รันในเบราว์เซอร์ที่รองรับ module | Read/Write (Boolean) |
แก้ไขจากต้นฉบับ: ตารางคุณสมบัติในต้นฉบับมีคำอธิบายผิดบางส่วน (เช่น defer อธิบายว่า src, charset ขาดหายไป) - ตารางข้างต้นแก้ไขแล้ว
ตัวอย่างการใช้งาน
<!DOCTYPE html>
<html>
<head>
<style>
body { text-align: center; font-family: sans-serif; padding: 2rem; background: #fff; color: #0197F6; }
h1 { color: #23CE6B; }
.btn {
background: #fff;
border: 2px dashed #0197F6;
color: #0197F6;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
width: 60%; max-width: 300px;
display: block;
margin: 1rem auto;
transition: all 0.2s;
}
.btn:hover { background: #0197F6; color: white; }
</style>
</head>
<body>
<h1>DOM Script Object Demo</h1>
<p>คลิกปุ่มเพื่อสร้าง <script> element แบบไดนามิก</p>
<button class="btn" onclick="createInlineScript()">สร้าง Inline Script</button>
<button class="btn" onclick="createExternalScript()">โหลด External Script</button>
<button class="btn" onclick="createModuleScript()">สร้าง ES Module Script</button>
<div id="log" style="margin-top: 2rem; text-align: left; max-width: 600px; margin-left: auto; margin-right: auto; font-family: monospace; background: #f5f5f5; padding: 1rem; border-radius: 8px;"></div>
<script>
function log(msg) {
const el = document.getElementById('log');
el.textContent += '\n' + new Date().toLocaleTimeString() + ' - ' + msg;
el.scrollTop = el.scrollHeight;
}
function createInlineScript() {
const script = document.createElement('script');
script.text = "log('Inline script executed!'); confirm('Inline script รันแล้ว!')";
document.body.appendChild(script);
log('สร้าง inline script');
}
function createExternalScript() {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js';
script.async = true;
script.onload = () => log('External script loaded: lodash');
script.onerror = () => log('External script failed to load');
document.head.appendChild(script);
log('เริ่มโหลด external script (async)');
}
function createModuleScript() {
const script = document.createElement('script');
script.type = 'module';
script.text = `
import { shuffle } from 'https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.esm.js';
log('ES Module loaded, shuffle([1,2,3]) = ' + JSON.stringify(shuffle([1,2,3])));
`;
document.body.appendChild(script);
log('สร้าง ES module script');
}
</script>
</body>
</html>
async vs defer vs module
<!-- โหลดแบบปกติ - บล็อก parsing จนโหลดและรันเสร็จ -->
<script src="app.js"></script>
<!-- async - โหลดขนานกัน รันทันทีที่โหลดเสร็จ (ลำดับไม่รับประกัน) -->
<script src="analytics.js" async></script>
<!-- defer - โหลดขนานกัน รันหลัง parsing จบ ตามลำดับ -->
<script src="app.js" defer></script>
<!-- module - ES6 module (defer โดยอัตโนมัติ) -->
<script type="module" src="app.mjs"></script>
<!-- nomodule - fallback สำหรับเบราว์เซอร์เก่า -->
<script nomodule src="legacy.js"></script>
Dynamic Script Loading Patterns
// 1. Load script with Promise
function loadScript(src, options = {}) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.async = options.async !== false;
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Failed to load ${src}`));
if (options.integrity) script.integrity = options.integrity;
if (options.crossOrigin) script.crossOrigin = options.crossOrigin;
document.head.appendChild(script);
});
}
// ใช้งาน
loadScript('https://cdn.example.com/lib.js')
.then(() => console.log('Loaded!'))
.catch(err => console.error(err));
// 2. Dynamic import (ES Modules) - แนะนำสำหรับ modern apps
async function loadModule() {
const module = await import('./module.js');
module.default();
}
เหตุการณ์ (Events)
onload- โหลดสำเร็จonerror- โหลดล้มเหลวonreadystatechange- สำหรับ IE เก่า (readyState: loading, loaded, complete)
Security Best Practices
- ใช้
integrity(SRI) สำหรับ CDN scripts - ใช้
crossorigin="anonymous"ร่วมกับ SRI - หลีกเลี่ยง
eval()และnew Function()กับ user input - Content Security Policy (CSP) header เพื่อจำกัด script sources