脚本使作者可以给他们的文档添加交互。
鼓励作者尽量使用声明式的标记替代脚本,因为声明式的机制更容易维护,而且很多用户禁用了脚本。
例如,显示和隐藏细节内容部分的脚本可以使用 details
元素替代。
也鼓励作者在没有脚本支持时对其应用优雅降级。
例如,如果作者在表格标题提供了一个重新排序的链接, 就可以把这个链接做成去服务器请求排好序的表格, 这样在没有脚本支持时也能完成功能。
script
elementSupport in all current engines.
Support in all current engines.
src
attribute, depends on the value of the type
attribute, but must match
script content restrictions.src
attribute, the element must be either empty or contain only
script documentation that also matches script
content restrictions.src
— Address of the resourcetype
— Type of scriptnomodule
— Prevents execution in user agents that support module scriptsasync
— Execute script when available, without blocking while fetchingdefer
— Defer script executioncrossorigin
— How the element handles crossorigin requestsintegrity
— Integrity metadata used in Subresource Integrity checks [SRI]referrerpolicy
— Referrer policy for fetches initiated by the element[Exposed=Window]
interface HTMLScriptElement : HTMLElement {
[HTMLConstructor] constructor();
[CEReactions] attribute USVString src;
[CEReactions] attribute DOMString type;
[CEReactions] attribute boolean noModule;
[CEReactions] attribute boolean async;
[CEReactions] attribute boolean defer;
[CEReactions] attribute DOMString? crossOrigin;
[CEReactions] attribute DOMString text;
[CEReactions] attribute DOMString integrity;
[CEReactions] attribute DOMString referrerPolicy;
// also has obsolete members
};
The script
element allows authors to include dynamic script and data blocks in
their documents. The element does not represent content for the
user.
Support in all current engines.
The type
attribute
allows customization of the type of script represented:
Omitting the attribute, setting it to the empty string, or setting it to a
JavaScript MIME type essence match, means that the script is a classic
script, to be interpreted according to the JavaScript Script top-level production. Classic scripts are affected by the
async
and defer
attributes, but only when the src
attribute is set.
Authors should omit the type
attribute instead of
redundantly setting it.
Setting the attribute to an ASCII case-insensitive match for the string
"module
" means that the script is a module script, to be
interpreted according to the JavaScript Module top-level
production. Module scripts are not affected by the defer
attribute, but are affected by the async
attribute
(regardless of the state of the src
attribute).
Setting the attribute to any other value means that the script is a data
block, which is not processed. None of the script
attributes (except type
itself) have any effect on data blocks. Authors must use
a valid MIME type string that is not a JavaScript MIME type essence
match to denote data blocks.
The requirement that data blocks
must be denoted using a valid MIME type string is in place to
avoid potential future collisions. If this specification ever adds additional types of
script, they will be triggered by setting the type
attribute to something which is not a MIME type, like how
the "module
" value denotes module
scripts. By using a valid MIME type string now, you ensure that your data block will not
ever be reinterpreted as a different script type, even in future user agents.
Classic scripts and module
scripts can be embedded inline, or be imported from an external file using the src
attribute, which if
specified gives the URL of the external script resource to use. If src
is specified, it must be a valid non-empty URL
potentially surrounded by spaces. The contents of inline script
elements, or
the external script resource, must conform with the requirements of the JavaScript specification's
Script or Module productions, for
classic scripts and module
scripts respectively. [JAVASCRIPT]
When used to include data blocks, the data must be embedded
inline, the format of the data must be given using the type
attribute, and the contents of the script
element must conform to the requirements
defined for the format used. The src
, async
, nomodule
,
defer
, crossorigin
, integrity
, and referrerpolicy
attributes must not be specified.
The nomodule
attribute is a boolean attribute that prevents a script from being executed in user
agents that support module scripts. This allows selective
execution of module scripts in modern user agents and classic scripts in older user agents, as shown below. The nomodule
attribute must not be specified on module scripts (and will be ignored if it is).
Support in all current engines.
Support in all current engines.
The async
and
defer
attributes are boolean attributes that indicate how the script should be evaluated. Classic scripts may specify defer
or async
, but must
not specify either unless the src
attribute is present.
Module scripts may specify the async
attribute, but must not specify the defer
attribute.
There are several possible modes that can be selected using these attributes, and depending on the script's type.
For classic scripts, if the async
attribute is present, then the classic script will be
fetched in parallel to parsing and evaluated as soon as it is available (potentially
before parsing completes). If the async
attribute is not
present but the defer
attribute is present, then the
classic script will be fetched in parallel and evaluated when the page has finished
parsing. If neither attribute is present, then the script is fetched and evaluated immediately,
blocking parsing until these are both complete.
For module scripts, if the async
attribute is present, then the module script and all its
dependencies will be fetched in parallel to parsing, and the module script will
be evaluated as soon as it is available (potentially before parsing completes). Otherwise, the
module script and its dependencies will be fetched in parallel to parsing and
evaluated when the page has finished parsing. (The defer
attribute has no effect on module scripts.)
This is all summarized in the following schematic diagram:
The exact processing details for these attributes are, for mostly historical
reasons, somewhat non-trivial, involving a number of aspects of HTML. The implementation
requirements are therefore by necessity scattered throughout the specification. The algorithms
below (in this section) describe the core of this processing, but these algorithms reference and
are referenced by the parsing rules for script
start and end tags in HTML, in foreign content,
and in XML, the rules for the document.write()
method, the handling of scripting, etc.
The defer
attribute may be specified even if the async
attribute is specified, to cause legacy web browsers that
only support defer
(and not async
) to fall back to the defer
behavior instead of the blocking behavior that
is the default.
The crossorigin
attribute is a CORS settings
attribute. For classic scripts, it controls whether
error information will be exposed, when the script is obtained from other origins. For module scripts, it
controls the credentials mode used for
cross-origin requests.
Unlike classic scripts, module scripts require the use of the CORS protocol for cross-origin fetching.
The integrity
attribute represents the integrity
metadata for requests which this element is responsible for. The value is text. The integrity
attribute must not be specified when the src
attribute is not specified. [SRI]
The referrerpolicy
attribute is a referrer
policy attribute. Its purpose is to set the referrer policy used when fetching the script, as well as any scripts imported from it. [REFERRERPOLICY]
An example of a script
element's referrer policy being used when fetching
imported scripts but not other subresources:
<script referrerpolicy="origin">
fetch('/api/data'); // not fetched with <script>'s referrer policy
import('./utils.mjs'); // is fetched with <script>'s referrer policy ("origin" in this case)
</script>
Changing the src
, type
, nomodule
, async
, defer
, crossorigin
, integrity
, and referrerpolicy
attributes dynamically has no direct effect; these
attributes are only used at specific times described below.
The IDL attributes src
, type
,
defer
, and integrity
, must each reflect the
respective content attributes of the same name.
HTMLScriptElement/referrerPolicy
Support in all current engines.
The referrerPolicy
IDL attribute must
reflect the referrerpolicy
content
attribute, limited to only known values.
The crossOrigin
IDL attribute must
reflect the crossorigin
content
attribute, limited to only known values.
The noModule
IDL attribute must
reflect the nomodule
content
attribute.
The async
IDL attribute controls whether the element will execute asynchronously or not. If the element's
"non-blocking" flag is set, then, on getting, the async
IDL attribute must return true, and on setting, the
"non-blocking" flag must first be unset, and then the content attribute must be
removed if the IDL attribute's new value is false, and must be set to the empty string if the IDL
attribute's new value is true. If the element's "non-blocking" flag is not
set, the IDL attribute must reflect the async
content attribute.
text
[ = value ]Returns the child text content of the element.
Can be set, to replace the element's children with the given value.
The text
attribute's getter must return this script
element's child text
content.
The text
attribute's setter must string replace
all with the given value within this script
element.
When inserted using the document.write()
method, script
elements usually
execute (typically blocking further script execution or HTML parsing). When inserted using the
innerHTML
and outerHTML
attributes, they do not execute at all.
In this example, two script
elements are used. One embeds an external
classic script, and the other includes some data as a data block.
<script src="game-engine.js"></script>
<script type="text/x-game-map">
........U.........e
o............A....e
.....A.....AAA....e
.A..AAA...AAAAA...e
</script>
The data in this case might be used by the script to generate the map of a video game. The data doesn't have to be used that way, though; maybe the map data is actually embedded in other parts of the page's markup, and the data block here is just used by the site's search engine to help users who are looking for particular features in their game maps.
The following sample shows how a script
element can be used to define a function
that is then used by other parts of the document, as part of a classic script. It
also shows how a script
element can be used to invoke script while the document is
being parsed, in this case to initialize the form's output.
<script>
function calculate(form) {
var price = 52000;
if (form.elements.brakes.checked)
price += 1000;
if (form.elements.radio.checked)
price += 2500;
if (form.elements.turbo.checked)
price += 5000;
if (form.elements.sticker.checked)
price += 250;
form.elements.result.value = price;
}
</script>
<form name="pricecalc" onsubmit="return false" onchange="calculate(this)">
<fieldset>
<legend>Work out the price of your car</legend>
<p>Base cost: £52000.</p>
<p>Select additional options:</p>
<ul>
<li><label><input type=checkbox name=brakes> Ceramic brakes (£1000)</label></li>
<li><label><input type=checkbox name=radio> Satellite radio (£2500)</label></li>
<li><label><input type=checkbox name=turbo> Turbo charger (£5000)</label></li>
<li><label><input type=checkbox name=sticker> "XZ" sticker (£250)</label></li>
</ul>
<p>Total: £<output name=result></output></p>
</fieldset>
<script>
calculate(document.forms.pricecalc);
</script>
</form>
The following sample shows how a script
element can be used to include an
external module script.
<script type="module" src="app.mjs"></script>
This module, and all its dependencies (expressed through JavaScript import
statements in the source file), will be fetched. Once the entire
resulting module graph has been imported, and the document has finished parsing, the contents of
app.mjs
will be evaluated.
Additionally, if code from another script
element in the same Window
imports the module from app.mjs
(e.g. via import
"./app.mjs";
), then the same module script created by the
former script
element will be imported.
This example shows how to include a module script for modern user agents, and a classic script for older user agents:
<script type="module" src="app.mjs"></script>
<script nomodule defer src="classic-app-bundle.js"></script>
In modern user agents that support module scripts, the
script
element with the nomodule
attribute
will be ignored, and the script
element with a type
of "module
" will be fetched and
evaluated (as a module script). Conversely, older user agents will ignore the
script
element with a type
of "module
", as that is an unknown script type for them — but they will have no
problem fetching and evaluating the other script
element (as a classic
script), since they do not implement the nomodule
attribute.
The following sample shows how a script
element can be used to write an inline
module script that performs a number of substitutions on the document's text, in
order to make for a more interesting reading experience (e.g. on a news site): [XKCD1288]
<script type="module">
import { walkAllTextNodeDescendants } from "./dom-utils.mjs";
const substitutions = new Map([
["witnesses", "these dudes I know"]
["allegedly", "kinda probably"]
["new study", "Tumblr post"]
["rebuild", "avenge"]
["space", "spaaace"]
["Google glass", "Virtual Boy"]
["smartphone", "Pokédex"]
["electric", "atomic"]
["Senator", "Elf-Lord"]
["car", "cat"]
["election", "eating contest"]
["Congressional leaders", "river spirits"]
["homeland security", "Homestar Runner"]
["could not be reached for comment", "is guilty and everyone knows it"]
]);
function substitute(textNode) {
for (const [before, after] of substitutions.entries()) {
textNode.data = textNode.data.replace(new RegExp(`\\b${before}\\b`, "ig"), after);
}
}
walkAllTextNodeDescendants(document.body, substitute);
</script>
Some notable features gained by using a module script include the ability to import functions
from other JavaScript modules, strict mode by default, and how top-level declarations do not
introduce new properties onto the global object. Also note that no matter where
this script
element appears in the document, it will not be evaluated until both
document parsing has complete and its dependency (dom-utils.mjs
) has been
fetched and evaluated.
A script
element has several associated pieces of state.
A script
element has a flag indicating whether or not it has been "already
started". Initially, script
elements must have this flag unset (script blocks,
when created, are not "already started"). The cloning
steps for script
elements must set the "already started" flag on the copy if
it is set on the element being cloned.
A script
element has a parser document, which is either null or a
Document
. Initially, its value must be null. It is set by the HTML
parser and the XML parser on script
elements they insert, and
affects the processing of those elements. script
elements with non-null parser documents are known as "parser-inserted".
A script
element has a flag indicating whether the element will be
"non-blocking". Initially, script
elements must have this flag set. It is
unset by the HTML parser and the XML parser on script
elements they insert. In addition, whenever a script
element whose
"non-blocking" flag is set has an async
content attribute added, the element's "non-blocking" flag must be unset.
A script
element has a flag indicating whether or not the script block is
"ready to be parser-executed". Initially, script
elements must have this
flag unset (script blocks, when created, are not "ready to be parser-executed"). This flag is used
only for elements that are also "parser-inserted", to let the parser know when to
execute the script.
The script's type for a script
element
is either "classic
" or "module
". It is determined
when the script is prepared, based on the type
attribute of the element at that time.
A script
element has a preparation-time document, which is a
Document
determined near the beginning of the prepare a script
algorithm. It is used to prevent scripts that move between documents during preparation from executing.
A script
element has a flag indicating whether or not the script is from an external file. It is determined when the script is
prepared, based on the src
attribute of the element at that time.
The script's script for a script
element is either null or a script resulting from preparing the element. This is set asynchronously after the
classic script or module graph is fetched. Once it is set, either to a script in the case of success or to null in the case of failure,
the fetching algorithms will note that the script is ready, which can trigger other
actions. The user agent must delay the load
event of the element's node document until the script is
ready.
When a script
element that is not "parser-inserted" experiences one
of the events listed in the following list, the user agent must immediately prepare the script
element:
script
element becomes connected.script
element is connected and a node or document fragment is
inserted into the script
element, after any
script
elements inserted at that time.script
element is connected and has a src
attribute set where previously the element had no such
attribute.To prepare a script, the user agent must act as follows:
If the script
element is marked as having "already started", then
return. The script is not executed.
Let parser document be the element's parser document.
Set the element's parser document to null.
This is done so that if parser-inserted script
elements fail to run
when the parser tries to run them, e.g. because they are empty or specify an unsupported
scripting language, another script can later mutate them and cause them to run again.
If parser document is non-null and the element does not have an async
attribute, then set the element's
"non-blocking" flag to true.
This is done so that if a parser-inserted script
element fails to
run when the parser tries to run it, but it is later executed after a script dynamically updates
it, it will execute in a non-blocking fashion even if the async
attribute isn't set.
Let source text be the element's child text content.
If the element has no src
attribute, and source
text is the empty string, then return. The script is not executed.
If the element is not connected, then return. The script is not executed.
If either:
script
element has a type
attribute
and its value is the empty string, orscript
element has no type
attribute
but it has a language
attribute and that
attribute's value is the empty string, orscript
element has neither a type
attribute nor a language
attribute, then...let the script block's type string for this script
element be
"text/javascript
".
Otherwise, if the script
element has a type
attribute, let the script block's type string
for this script
element be the value of that attribute with leading and trailing ASCII whitespace
stripped.
Otherwise, the element has a non-empty language
attribute; let the script block's type string for this script
element
be the concatenation of the string "text/
" followed by the value of the
language
attribute.
The language
attribute is never
conforming, and is always ignored if there is a type
attribute present.
Determine the script's type as follows:
classic
".module
", the
script's type is "module
".If parser document is non-null, then set the element's parser document back to parser document and set the element's "non-blocking" flag to false.
Set the element's "already started" flag.
Set the element's preparation-time document to its node document.
If parser document is non-null, and parser document is not equal to the element's preparation-time document, then return.
If scripting is disabled for the script
element, then return. The script is not executed.
The definition of scripting is disabled
means that, amongst others, the following scripts will not execute: scripts in
XMLHttpRequest
's responseXML
documents, scripts in DOMParser
-created documents, scripts in documents created by
XSLTProcessor
's transformToDocument
feature, and scripts
that are first inserted by a script into a Document
that was created using the
createDocument()
API. [XHR]
[DOMPARSING] [XSLTP] [DOM]
If the script
element has a nomodule
content attribute and the script's type is "classic
", then return. The script is not executed.
This means specifying nomodule
on a
module script has no effect; the algorithm continues onward.
If the script
element does not have a src
content attribute, and the Should element's inline
behavior be blocked by Content Security Policy? algorithm returns "Blocked
" when executed upon the script
element, "script
", and source text, then return. The script is not executed.
[CSP]
If the script
element has an event
attribute and a for
attribute, and the script's type is "classic
",
then:
Let for be the value of the for
attribute.
Let event be the value of the event
attribute.
Strip leading and trailing ASCII whitespace from event and for.
If for is not an ASCII case-insensitive match for the
string "window
", then return. The script is not executed.
If event is not an ASCII case-insensitive match for
either the string "onload
" or the string "onload()
", then return. The script is not executed.
If the script
element has a charset
attribute, then let encoding be the result of getting an encoding from
the value of the charset
attribute.
If the script
element does not have a charset
attribute, or if getting an encoding
failed, let encoding be the same as the
encoding of the script
element's node document.
If the script's type is "module
", this encoding will be ignored.
Let classic script CORS setting be the current state of the element's crossorigin
content attribute.
Let module script credentials mode be the CORS settings attribute
credentials mode for the element's crossorigin
content attribute.
Let cryptographic nonce be the element's [[CryptographicNonce]] internal slot's value.
If the script
element has an integrity
attribute, then let integrity
metadata be that attribute's value.
Otherwise, let integrity metadata be the empty string.
Let referrer policy be the current state of the element's referrerpolicy
content attribute.
Let parser metadata be "parser-inserted
" if the
script
element is "parser-inserted", and "not-parser-inserted
" otherwise.
Let options be a script fetch options whose cryptographic nonce is cryptographic nonce, integrity metadata is integrity metadata, parser metadata is parser metadata, credentials mode is module script credentials mode, and referrer policy is referrer policy.
Let settings object be the element's node document's relevant settings object.
If the element has a src
content attribute, then:
Let src be the value of the element's src
attribute.
If src is the empty string, queue a task to fire an event named error
at the element, and return.
Set the element's from an external file flag.
Parse src relative to the element's node document.
If the previous step failed, queue a task to fire an event named error
at the element, and return. Otherwise, let url be the resulting URL
record.
Switch on the script's type:
classic
"Fetch a classic script given url, settings object, options, classic script CORS setting, and encoding.
module
"Fetch an external module script graph given url, settings object, and options.
When the chosen algorithm asynchronously completes, set the script's script to the result. At that time, the script is ready.
For performance reasons, user agents may start fetching the classic script or module graph
(as defined above) as soon as the src
attribute is set,
instead, in the hope that the element will be inserted into the document (and that the crossorigin
attribute won't change value in the
meantime). Either way, once the element is inserted into the document, the load must have started as described in this
step. If the UA performs such prefetching, but the element is never inserted in the document,
or the src
attribute is dynamically changed, or the crossorigin
attribute is dynamically changed, then the
user agent will not execute the script so obtained, and the fetching process will have been
effectively wasted.
If the element does not have a src
content attribute,
run these substeps:
Let base URL be the script
element's node
document's document base URL.
Switch on the script's type:
classic
"Let script be the result of creating a classic script using source text, settings object, base URL, and options.
Set the script's script to script.
module
"Fetch an inline module script graph, given source text, base URL, settings object, and options. When this asynchronously completes, set the script's script to the result. At that time, the script is ready.
Then, follow the first of the following options that describes the situation:
classic
", and the element has a src
attribute, and the element has a defer
attribute, and the element is
"parser-inserted", and the element does not have an async
attributemodule
", and
the element is "parser-inserted", and the element does not have an async
attributeAdd the element to the end of the list of scripts that will execute when the document
has finished parsing associated with the Document
of the parser that
created the element.
When the script is ready, set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
classic
", and the element has a src
attribute, and the element is
"parser-inserted", and the element does not have an async
attributeThe element is the pending parsing-blocking script of the
Document
of the parser that created the element. (There can only be one such
script per Document
at a time.)
When the script is ready, set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
classic
", and the element has a src
attribute, and the element does not have an async
attribute, and the element does not have the
"non-blocking" flag setmodule
", and the element does not have an async
attribute, and the element does not have the
"non-blocking" flag setAdd the element to the end of the list of scripts that will execute in order as soon as possible associated with the element's preparation-time document.
When the script is ready, run the following steps:
If the element is not now the first element in the list of scripts that will execute in order as soon as possible to which it was added above, then mark the element as ready but return without executing the script yet.
Execution: Execute the script block corresponding to the first script element in this list of scripts that will execute in order as soon as possible.
Remove the first element from this list of scripts that will execute in order as soon as possible.
If this list of scripts that will execute in order as soon as possible is still not empty and the first entry has already been marked as ready, then jump back to the step labeled execution.
classic
", and the element has a src
attributemodule
"The element must be added to the set of scripts that will execute as soon as possible of the element's preparation-time document.
When the script is ready, execute the script block and then remove the element from the set of scripts that will execute as soon as possible.
src
attribute, and the element is
"parser-inserted", and either the parser that created the script
is
an XML parser or it's an HTML parser whose script nesting
level is not greater than one, and the element's parser document has
a style sheet that is blocking scriptsThe element is the pending parsing-blocking script of its parser
document. (There can only be one such script per Document
at a time.)
Set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
The pending parsing-blocking script of a Document
is used by the
Document
's parser(s).
If a script
element that blocks a parser gets moved to another
Document
before it would normally have stopped blocking that parser, it nonetheless
continues blocking that parser until the condition that causes it to be blocking the parser no
longer applies (e.g., if the script is a pending parsing-blocking script because the
original Document
has a style sheet that is blocking scripts when it was
parsed, but then the script is moved to another Document
before the blocking style
sheet(s) loaded, the script still blocks the parser until the style sheets are all loaded, at
which time the script executes and the parser is unblocked).
To execute a script block given a
script
element scriptElement:
Let document be scriptElement's node document.
If scriptElement's preparation-time document is not equal to document, then return.
If the script's script is null for
scriptElement, then fire an event named error
at scriptElement, and return.
If scriptElement is from an external
file, or the script's type for
scriptElement is "module
", then increment document's
ignore-destructive-writes counter.
Switch on the script's type for scriptElement:
classic
"Let oldCurrentScript be the value to which document's currentScript
object was most recently
set.
If scriptElement's root is not a shadow
root, then set document's currentScript
attribute to
scriptElement. Otherwise, set it to null.
This does not use the in a document tree check, as
scriptElement could have been removed from the document prior to execution, and
in that scenario currentScript
still needs
to point to it.
Run the classic script given by the script's script for scriptElement.
Set document's currentScript
attribute to
oldCurrentScript.
module
"Assert: document's currentScript
attribute is null.
Run the module script given by the script's script for scriptElement.
Decrement the ignore-destructive-writes counter of document, if it was incremented in the earlier step.
If scriptElement is from an external
file, then fire an event named load
at scriptElement.
User agents are not required to support JavaScript. This standard needs to be updated
if a language other than JavaScript comes along and gets similar wide adoption by web browsers.
Until such a time, implementing other languages is in conflict with this standard, given the
processing model defined for the script
element.
Servers should use text/javascript
for JavaScript resources. Servers should not
use other JavaScript MIME types for JavaScript
resources, and must not use non-JavaScript MIME
types.
For external JavaScript resources, MIME type parameters in `Content-Type
` headers
are generally ignored. (In some cases the `charset
` parameter has an
effect.) However, for the script
element's type
attribute they are significant; it uses the JavaScript
MIME type essence match concept.
For example, scripts with their type
attribute set to "text/javascript; charset=utf-8
" will not be
evaluated, even though that is a valid JavaScript MIME type when parsed.
Furthermore, again for external JavaScript resources, special considerations apply around
`Content-Type
` header processing as detailed in the prepare a script
algorithm and Fetch. [FETCH]
script
元素内容的限制避免本章中描述的这些奇怪限制的最简单安全的方式就是总是转义
"<!--
" 为 "<\!--
",
"<script
" 为 "<\script
",
"</script
" 为 "<\/script
"
(例如在字符串中、正则表达式中,或者注释中),同时避免编写在表达式中使用这些构造的代码。
这样就可以避免本章中的限制产生的陷阱:
即,由于历史原因在 HTML 中解析 script
块是一个奇怪的过程,
碰到这些序列时表现地很不直观。
script
元素的 textContent
必须匹配
下面的 script
的 ABNF 生成式,其中的字符集是 Unicode。
[ABNF]
script = outer *( comment-open inner comment-close outer ) outer = < any string that doesn't contain a substring that matches not-in-outer > not-in-outer = comment-open inner = < any string that doesn't contain a substring that matches not-in-inner > not-in-inner = comment-close / script-open comment-open = "<!--" comment-close = "-->" script-open = "<" s c r i p t tag-end s = %x0053 ; U+0053 LATIN CAPITAL LETTER S s =/ %x0073 ; U+0073 LATIN SMALL LETTER S c = %x0043 ; U+0043 LATIN CAPITAL LETTER C c =/ %x0063 ; U+0063 LATIN SMALL LETTER C r = %x0052 ; U+0052 LATIN CAPITAL LETTER R r =/ %x0072 ; U+0072 LATIN SMALL LETTER R i = %x0049 ; U+0049 LATIN CAPITAL LETTER I i =/ %x0069 ; U+0069 LATIN SMALL LETTER I p = %x0050 ; U+0050 LATIN CAPITAL LETTER P p =/ %x0070 ; U+0070 LATIN SMALL LETTER P t = %x0054 ; U+0054 LATIN CAPITAL LETTER T t =/ %x0074 ; U+0074 LATIN SMALL LETTER T tag-end = %x0009 ; U+0009 CHARACTER TABULATION (tab) tag-end =/ %x000A ; U+000A LINE FEED (LF) tag-end =/ %x000C ; U+000C FORM FEED (FF) tag-end =/ %x0020 ; U+0020 SPACE tag-end =/ %x002F ; U+002F SOLIDUS (/) tag-end =/ %x003E ; U+003E GREATER-THAN SIGN (>)
当 script
元素包含 脚本文档 时,
对该元素的内容有更多的限制,描述如下。
下面的脚本演示了这个问题,假设你有一个标签包含这样的字符串:
var example = 'Consider this string: <!-- <script>'; console.log(example);
如果有人直接把这个字符串放到 script
块中,就会违反上述限制:
restrictions above:
<script> var example = 'Consider this string: <!-- <script>'; console.log(example); </script>
更大的问题(也即违反那些规则的原因)是脚本的解析会很奇怪:
上述脚本块并未结束。
也就是说,看起来是结束标签的 "</script>
" 实际上仍然是
script
块的内容。这个脚本不会执行(因为它没有结束);
如果它最终还是执行了(比如下面的情况),它会因为脚本不合法(下面有高亮)而失败:
<script> var example = 'Consider this string: <!-- <script>'; console.log(example); </script> <!-- despite appearances, this is actually part of the script still! --> <script> ... // this is the same script block still... </script>
这种行为是历史原因造成的,在 HTML 中 script
元素中的
"<!--
" 和 "<script
"
字符串需要匹配,才能让解析器认为块已经结束。
参照本章开始提到的方式转义这个出问题的字符串,就可以完全避免这个问题:
<script> var example = 'Consider this string: <\!-- <\script>'; console.log(example); </script> <!-- this is just a comment between script blocks --> <script> ... // this is a new script block </script>
这种字符序列在正常的脚本表达式中也可能出现,比如下面这个例子:
if (x<!--y) { ... } if ( player<script ) { ... }
这种情况下无法转义这些字符,但可以重写表达式来避免这个字符序列,如:
if (x < !--y) { ... } if (!--y > x) { ... } if (!(--y) > x) { ... } if (player < script) { ... } if (script > player) { ... }
这样做还能避免另一个陷阱:由于相关的历史原因, 在 经典脚本 中字符串 "<!--" 实际上被处理为行注释的开始,就像 "//" 一样。
If a script
element's src
attribute is
specified, then the contents of the script
element, if any, must be such that the
value of the text
IDL attribute, which is derived from the
element's contents, matches the documentation
production in the following
ABNF, the character set for which is Unicode. [ABNF]
documentation = *( *( space / tab / comment ) [ line-comment ] newline )
comment = slash star *( not-star / star not-slash ) 1*star slash
line-comment = slash slash *not-newline
; characters
tab = %x0009 ; U+0009 CHARACTER TABULATION (tab)
newline = %x000A ; U+000A LINE FEED (LF)
space = %x0020 ; U+0020 SPACE
star = %x002A ; U+002A ASTERISK (*)
slash = %x002F ; U+002F SOLIDUS (/)
not-newline = %x0000-0009 / %x000B-10FFFF
; a scalar value other than U+000A LINE FEED (LF)
not-star = %x0000-0029 / %x002B-10FFFF
; a scalar value other than U+002A ASTERISK (*)
not-slash = %x0000-002E / %x0030-10FFFF
; a scalar value other than U+002F SOLIDUS (/)
This corresponds to putting the contents of the element in JavaScript comments.
This requirement is in addition to the earlier restrictions on the syntax of
contents of script
elements.
This allows authors to include documentation, such as license information or API information,
inside their documents while still referring to external script files. The syntax is constrained
so that authors don't accidentally include what looks like valid script while also providing a
src
attribute.
<script src="cool-effects.js">
// create new instances using:
// var e = new Effect();
// start the effect using .play, stop using .stop:
// e.play();
// e.stop();
</script>
script
elements and XSLTThis section is non-normative.
This specification does not define how XSLT interacts with the script
element.
However, in the absence of another specification actually defining this, here are some guidelines
for implementers, based on existing implementations:
When an XSLT transformation program is triggered by an <?xml-stylesheet?>
processing instruction and the browser implements a
direct-to-DOM transformation, script
elements created by the XSLT processor need to
have its parser document set correctly, and run in document order (modulo scripts
marked defer
or async
), immediately, as the transformation is
occurring.
The XSLTProcessor
transformToDocument()
method adds elements
to a Document
object with a null browsing
context, and, accordingly, any script
elements they create need to have their
"already started" flag set in the prepare a script algorithm and never
get executed (scripting is disabled). Such
script
elements still need to have their parser document set, though,
such that their async
IDL attribute will return false in
the absence of an async
content attribute.
The XSLTProcessor
transformToFragment()
method needs to
create a fragment that is equivalent to one built manually by creating the elements using document.createElementNS()
. For instance, it needs
to create script
elements with null parser document and that don't have
their "already started" flag set, so that they will execute when the fragment is
inserted into a document.
The main distinction between the first two cases and the last case is that the first two
operate on Document
s and the last operates on a fragment.
noscript
elementSupport in all current engines.
head
element of an HTML document, if there are no ancestor noscript
elements.noscript
elements.head
element: in any order, zero or more link
elements, zero or more style
elements, and zero or more meta
elements.head
element: transparent, but there must be no noscript
element descendants.HTMLElement
.The noscript
element represents nothing if scripting is enabled, and represents its children if
scripting is disabled. It is used to present different
markup to user agents that support scripting and those that don't support scripting, by affecting
how the document is parsed.
When used in HTML documents, the allowed content model is as follows:
head
element, if scripting is
disabled for the noscript
elementThe noscript
element must contain only link
, style
,
and meta
elements.
head
element, if scripting is enabled
for the noscript
elementThe noscript
element must contain only text, except that invoking the
HTML fragment parsing algorithm with
the noscript
element as the context
element and the text contents as the input must result in a list of nodes
that consists only of link
, style
, and meta
elements that
would be conforming if they were children of the noscript
element, and no parse errors.
head
elements, if scripting is
disabled for the noscript
elementThe noscript
element's content model is transparent, with the
additional restriction that a noscript
element must not have a noscript
element as an ancestor (that is, noscript
can't be nested).
head
elements, if scripting is
enabled for the noscript
elementThe noscript
element must contain only text, except that the text must be such
that running the following algorithm results in a conforming document with no
noscript
elements and no script
elements, and such that no step in the
algorithm throws an exception or causes an HTML parser to flag a parse
error:
script
element from the document.noscript
element in the document. For every
noscript
element in that list, perform the following steps:
noscript
element.outerHTML
attribute of the
noscript
element to the value of s. (This, as a
side-effect, causes the noscript
element to be removed from the document.) [DOMPARSING]All these contortions are required because, for historical reasons, the
noscript
element is handled differently by the HTML parser based on
whether scripting was enabled or not when the parser was
invoked.
The noscript
element must not be used in XML documents.
The noscript
element is only effective in HTML
语法, it has no effect in XML 语法. This is because the way it works
is by essentially "turning off" the parser when scripts are enabled, so that the contents of the
element are treated as pure text and not as real elements. XML does not define a mechanism by
which to do this.
The noscript
element has no other requirements. In particular, children of the
noscript
element are not exempt from form submission, scripting, and so
forth, even when scripting is enabled for the element.
In the following example, a noscript
element is
used to provide fallback for a script.
<form action="calcSquare.php"> <p> <label for=x>Number</label>: <input id="x" name="x" type="number"> </p> <script> var x = document.getElementById('x'); var output = document.createElement('p'); output.textContent = 'Type a number; it will be squared right then!'; x.form.appendChild(output); x.form.onsubmit = function () { return false; } x.oninput = function () { var v = x.valueAsNumber; output.textContent = v + ' squared is ' + v * v; }; </script> <noscript> <input type=submit value="Calculate Square"> </noscript> </form>
When script is disabled, a button appears to do the calculation on the server side. When script is enabled, the value is computed on-the-fly instead.
The noscript
element is a blunt instrument. Sometimes, scripts might be enabled,
but for some reason the page's script might fail. For this reason, it's generally better to avoid
using noscript
, and to instead design the script to change the page from being a
scriptless page to a scripted page on the fly, as in the next example:
<form action="calcSquare.php"> <p> <label for=x>Number</label>: <input id="x" name="x" type="number"> </p> <input id="submit" type=submit value="Calculate Square"> <script> var x = document.getElementById('x'); var output = document.createElement('p'); output.textContent = 'Type a number; it will be squared right then!'; x.form.appendChild(output); x.form.onsubmit = function () { return false; } x.oninput = function () { var v = x.valueAsNumber; output.textContent = v + ' squared is ' + v * v; }; var submit = document.getElementById('submit'); submit.parentNode.removeChild(submit); </script> </form>
The above technique is also useful in XML documents, since noscript
is not allowed there.
template
elementSupport in all current engines.
Support in all current engines.
colgroup
element that doesn't have a span
attribute.[Exposed=Window]
interface HTMLTemplateElement : HTMLElement {
[HTMLConstructor] constructor();
readonly attribute DocumentFragment content;
};
The template
element is used to declare fragments of HTML that can be cloned and
inserted in the document by script.
In a rendering, the template
element represents nothing.
The template contents of a template
element are not children of the element itself.
It is also possible, as a result of DOM manipulation, for a template
element to contain Text
nodes and element nodes; however, having any is a violation
of the template
element's content model, since its content model is defined as nothing.
For example, consider the following document:
<!doctype html>
<html lang="en">
<head>
<title>Homework</title>
<body>
<template id="template"><p>Smile!</p></template>
<script>
let num = 3;
const fragment = document.getElementById('template').content.cloneNode(true);
while (num-- > 1) {
fragment.firstChild.before(fragment.firstChild.cloneNode(true));
fragment.firstChild.textContent += fragment.lastChild.textContent;
}
document.body.appendChild(fragment);
</script>
</html>
The p
element in the template
is not a child of the
template
in the DOM; it is a child of the DocumentFragment
returned by
the template
element's content
IDL
attribute.
If the script were to call appendChild()
on the
template
element, that would add a child to the template
element (as
for any other element); however, doing so is a violation of the template
element's
content model.
content
Support in all current engines.
Returns the template contents (a DocumentFragment
).
Each template
element has an associated DocumentFragment
object that
is its template contents. The template contents have no conformance requirements. When a template
element
is created, the user agent must run the following steps to establish the template
contents:
Let doc be the template
element's node document's appropriate template contents owner
document.
Create a DocumentFragment
object whose node document is
doc and host is the
template
element.
Set the template
element's template contents to the newly
created DocumentFragment
object.
A Document
doc's appropriate template contents owner
document is the Document
returned by the following algorithm:
If doc is not a Document
created by this algorithm, then:
If doc does not yet have an associated inert template document, then:
Let new doc be a new Document
(whose browsing context is null). This is "a
Document
created by this algorithm" for the purposes of the step above.
If doc is an HTML document, mark new doc as an HTML document also.
Let doc's associated inert template document be new doc.
Set doc to doc's associated inert template document.
Each Document
not created by this algorithm thus gets a single
Document
to act as its proxy for owning the template contents of all
its template
elements, so that they aren't in a browsing context and
thus remain inert (e.g. scripts do not run). Meanwhile, template
elements inside
Document
objects that are created by this algorithm just reuse the same
Document
owner for their contents.
Return doc.
The adopting steps
(with node and oldDocument as parameters) for template
elements
are the following:
Let doc be node's node document's appropriate template contents owner document.
node's node document is the Document
object
that node was just adopted into.
Adopt node's
template contents (a DocumentFragment
object) into doc.
The content
IDL attribute must return the
template
element's template contents.
The cloning steps for a template
element node being cloned to a copy copy must run the
following steps:
If the clone children flag is not set in the calling clone algorithm, return.
Let copied contents be the result of cloning all the children of node's template contents, with document set to copy's template contents's node document, and with the clone children flag set.
Append copied contents to copy's template contents.
In this example, a script populates a table four-column with data from a data structure, using
a template
to provide the element structure instead of manually generating the
structure from markup.
<!DOCTYPE html>
<html lang='en'>
<title>Cat data</title>
<script>
// Data is hard-coded here, but could come from the server
var data = [
{ name: 'Pillar', color: 'Ticked Tabby', sex: 'Female (neutered)', legs: 3 },
{ name: 'Hedral', color: 'Tuxedo', sex: 'Male (neutered)', legs: 4 },
];
</script>
<table>
<thead>
<tr>
<th>Name <th>Color <th>Sex <th>Legs
<tbody>
<template id="row">
<tr><td><td><td><td>
</template>
</table>
<script>
var template = document.querySelector('#row');
for (var i = 0; i < data.length; i += 1) {
var cat = data[i];
var clone = template.content.cloneNode(true);
var cells = clone.querySelectorAll('td');
cells[0].textContent = cat.name;
cells[1].textContent = cat.color;
cells[2].textContent = cat.sex;
cells[3].textContent = cat.legs;
template.parentNode.appendChild(clone);
}
</script>
This example uses cloneNode()
on the
template
's contents; it could equivalently have used document.importNode()
, which does the same thing. The
only difference between these two APIs is when the node document is updated: with
cloneNode()
it is updated when the nodes are appended
with appendChild()
, with document.importNode()
it is updated when the nodes are
cloned.
template
elements with XSLT and XPathThis section is non-normative.
This specification does not define how XSLT and XPath interact with the template
element. However, in the absence of another specification actually defining this, here are some
guidelines for implementers, which are intended to be consistent with other processing described
in this specification:
An XSLT processor based on an XML parser that acts as described
in this specification needs to act as if template
elements contain as
descendants their template contents for the purposes of the transform.
An XSLT processor that outputs a DOM needs to ensure that nodes that would go into a
template
element are instead placed into the element's template
contents.
XPath evaluation using the XPath DOM API when applied to a Document
parsed
using the HTML parser or the XML parser described in this specification
needs to ignore template contents.
slot
elementSupport in all current engines.
Support in all current engines.
name
— Name of shadow tree slot[Exposed=Window]
interface HTMLSlotElement : HTMLElement {
[HTMLConstructor] constructor();
[CEReactions] attribute DOMString name;
sequence<Node> assignedNodes(optional AssignedNodesOptions options = {});
sequence<Element> assignedElements(optional AssignedNodesOptions options = {});
};
dictionary AssignedNodesOptions {
boolean flatten = false;
};
The slot
element defines a slot. It is
typically used in a shadow tree. A slot
element represents
its assigned nodes, if any, and its contents otherwise.
The name
content attribute may contain any
string value. It represents a slot's name.
The name
attribute is used to assign slots to other elements: a slot
element with a
name
attribute creates a named slot to which any element is assigned if that element has a slot
attribute whose
value matches that name
attribute's value, and the
slot
element is a child of the shadow tree whose root's
host has that corresponding slot
attribute value.
name
Support in all current engines.
assignedNodes
()Support in all current engines.
assignedNodes
({ flatten: true })slot
elements encountered therein, recursively,
until there are no slot
elements left.assignedElements
()HTMLSlotElement/assignedElements
Support in all current engines.
assignedElements
({ flatten: true })assignedNodes({ flatten: true
})
, limited to elements.The name
IDL attribute must reflect
the content attribute of the same name.
The assignedNodes(options)
method, when invoked, must run these steps:
If the value of options's flatten
member is false, then
return this element's assigned nodes.
Return the result of finding flattened slottables with this element.
The assignedElements(options)
method, when invoked, must run these steps:
If the value of options's flatten
member is false, then
return this element's assigned nodes, filtered to contain only Element
nodes.
Return the result of finding flattened slottables with this element, filtered
to contain only Element
nodes.