选择器分类

  • 简单选择器(根据名称、id、类来选取元素)
  • 组合器选择器(根据它们之间的特定关系来选取元素)
  • 伪类选择器(根据特定状态选取元素)
  • 伪元素选择器(选取元素的一部分并设置其样式)
  • 属性选择器(根据属性或属性值来选取元素)

简单选择器

CSS 元素选择器

实例

在这里,页面上的所有

元素都将居中对齐,并带有红色文本颜色:

1
2
3
4
p {
text-align: center;
color: red;
}

CSS id 选择器

id 选择器可以为标有特定 id 的 HTML 元素指定特定的样式。

HTML元素以id属性来设置id选择器,CSS 中 id 选择器以 “#” 来定义。

以下的样式规则应用于元素属性 id=”para1”:

实例

1
2
3
4
5
#para1
{
text-align:center;
color:red;
}

注意:

ID属性不要以数字开头,数字开头的ID在 Mozilla/Firefox 浏览器中不起作用。

CSS 类选择器

class 选择器用于描述一组元素的样式,class 选择器有别于id选择器,class可以在多个元素中使用。

class 选择器在HTML中以class属性表示, 在 CSS 中,类选择器以一个点**”.”号**显示:

在以下的例子中,所有拥有 center 类的 HTML 元素均为居中。

实例

1
.center {text-align:center;}

你也可以指定特定的HTML元素使用class。

在以下实例中, 所有的 p 元素使用 class=”center” 让该元素的文本居中:

实例

1
p.center {text-align:center;}

注意:HTML 元素也可以引用多个类。

实例

在这个例子中,

元素将根据 class=”center” 和 class=”large” 进行样式设置:

1
<p class="center large">这个段落引用两个类。</p>

注意:类名不能以数字开头!

CSS 通用选择器

通用选择器(*)选择页面上的所有的 HTML 元素。

实例

下面的 CSS 规则会影响页面上的每个 HTML 元素:

1
2
3
4
* {
text-align: center;
color: blue;
}

CSS 分组选择器

分组选择器是元素选择器的衍生。

元素选择器:

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
h1 {
text-align: center;
color: red;
}

h2 {
text-align: center;
color: red;
}

p {
text-align: center;
color: red;
}

分组选择器,顾名思义就是将元素选择器选择的元素进行分组,上面的代码片段,因为想要三个元素的样式都相同,我们可以用分组选择器来这么写:

实例

1
2
3
4
h1, h2, p {
text-align: center;
color: red;
}

这样不仅实现了效果更简化了,代码片段。

所有简单的 CSS 选择器

选择器 例子 例子描述
.class (类选择器) .intro { //style} 选取所有 class=”intro” 的元素。
#id (id选择器) #firstname { //style} 选取 id=”firstname” 的那个元素。
* (通用选择器) * { //style} 选取所有元素。
element (元素选择器) p { //style} 选取所有

元素。

element*,*element,.. (分组选择器) iv, p { //style} 选取所有
元素和所有

元素。

CSS 组合器

在 CSS3 中包含了四种组合方式:

•后代选择器(以空格 分隔)

•子元素选择器(以大于 > 号分隔)

•相邻兄弟选择器(以加号 + 分隔)

•普通兄弟选择器(以波浪号 ~ 分隔)

后代选择器

后代选择器匹配属于指定元素后代的所有元素。

下面的例子选择

元素内的所有

元素:

1
2
3
div p {
background-color: yellow;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>
<head>
<style>
div p {
background-color: yellow;
}
</style>
</head>
<body>

<h1>后代选择器</h1>
<p>后代选择器匹配作为指定元素后代的所有元素。</p>

<div>
<p>div 中的段落 1。</p> //我有效果
<p>div 中的段落 2。</p>//我有效果
<section><p>div 中的段落 3。</p></section>//我有效果
</div>

<p>段落 4。不在 div 中。</p>
<p>段落 5。不在 div 中。</p>

</body>
</html>

子选择器

与后代选择器相比,它只能选择作为某元素**直接/一级子元素**的元素。

以下实例选择了

元素中所有直接子元素

1
2
3
div > p {
background-color: yellow;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<style>
div > p {
background-color: yellow;
}
</style>
</head>
<body>

<h1>子选择器</h1>
<p>子选择器 (>) 选择属于指定元素子元素的所有元素。</p>

<div>
<p>div 中的段落 1。</p> //我有效果
<p>div 中的段落 2。</p> //我有效果
<section><p>div 中的段落 3。</p></section> <!-- 非子但属后代 -->
<p>div 中的段落 4。</p> //我有效果
</div>

<p>段落 5。不在 div 中。</p>
<p>段落 6。不在 div 中。</p>

</body>
</html>

相邻兄弟选择器

相邻兄弟选择器匹配所有作为指定元素的相邻同级的元素。

兄弟(同级)元素必须具有相同的父元素,“相邻”的意思是“紧随其后”的第一个元素。

相邻兄弟选择器:可选择紧接在另一元素后的元素,且二者有相同父元素。

以下实例选取了所有位于

元素后的第一个

元素:

1
2
3
div + p {
background-color: yellow;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
<style>
div + p {
background-color: yellow;
}
</style>
</head>
<body>

<h1>相邻兄弟选择器</h1>
<p>相邻的同胞选择器(+)选择所有作为指定元素的相邻的同级元素。</p>

<div>
<p>div 中的段落 1。</p>
<p>div 中的段落 2。</p>
</div>

<p>段落 3。不在 div 中。</p> //只有我有效果
<p>段落 4。不在 div 中。</p>

</body>
</html>

后续(通用)兄弟选择器

后续兄弟选择器选取所有指定元素之后的相邻兄弟元素。

以下实例选取了所有

元素之后的所有相邻兄弟元素

:

1
2
3
div ~ p {
background-color: yellow;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<style>
div ~ p {
background-color: yellow;
}
</style>
</head>
<body>

<h1>通用兄弟选择器</h1>
<p>通用的兄弟选择器(~)选择指定元素的所有同级元素。</p>

<p>段落 1。</p>

<div>
<p>段落 2。</p>
</div>

<p>段落 3。</p>
<code>一些代码。</code>
<p>段落 4。</p>

</body>
</html>

所有 CSS 组合选择器

选择器 示例 示例描述
element element(后代选择器) div p {//style} 选择
元素内的所有

元素。

element>element (子选择器) div > p{//style} 选择其父元素是
元素的所有

元素。

element*+*element(相邻兄弟选择器) div + p{//style} 选择所有紧随
元素之后的

元素。

element1~element2(后续(通用)兄弟选择器) p ~ ul{//style} 选择前面有

元素的每个

    元素。

伪类选择器

伪类的语法

1
2
3
selector:pseudo-class {
property: value;
}

CSS类也可以使用伪类:

1
2
3
selector.class:pseudo-class {
property: value;
}

在支持 CSS 的浏览器中,链接的不同状态都可以以不同的方式显示

1
2
3
4
5
6
7
a:link {color:#FF0000;} /* 未访问的链接 */

a:visited {color:#00FF00;} /* 已访问的链接 */

a:hover {color:#FF00FF;} /* 鼠标划过链接 */

a:active {color:#0000FF;} /* 已选中的链接 */

注意:

•在CSS定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的。

•在 CSS 定义中,a:active 必须被置于 a:hover 之后,才是有效的。

•伪类的名称不区分大小写。

伪类可以与 CSS 类配合使用:

实例

1
2
3
a.red:visited {color:#FF0000;}

<a class="red" href="css-syntax.html">CSS 语法</a>

如果在上面的例子的链接已被访问,它会显示为红色。

伪类 —— :first-child伪类

使用 :first-child 伪类来选择父元素的第一个子元素。

注意:在IE8的之前版本必须声明<!DOCTYPE> ,这样 :first-child 才能生效。

匹配作为任何元素的第一个子元素的

元素:

1
2
3
4
p:first-child
{
color:blue;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<style>
p:first-child {
color: blue;
}
</style>
</head>
<body>

<p>这是一段文本。</p>

<p>这是一段文本。</p>

</body>
</html>

匹配所有

元素中的首个 元素

在下面的例子中,选择器匹配所有

元素中的第一个 元素:被选中的是i标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<style>
p i:first-child {
color: blue;
}
</style>
</head>
<body>

<p>我是一个<i>`强壮`</i>的男人。我是一个<i>强壮</i>的男人。</p>

<p>我是一个<i>`强壮`</i>的男人。我是一个<i>强壮</i>的男人。</p>

</body>
</html>

匹配所有首个

元素中的所有 元素

在下面的例子中,选择器匹配作为另一个元素的第一个子元素的

元素中的所有 元素:被选中的是p标签

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<style>
p:first-child i {
color: blue;
}
</style>
</head>
<body>

<p>我是一个<i>`强壮`</i>的男人。我是一个<i>`强壮`</i>的男人。</p>

<p>我是一个<i>强壮</i>的男人。我是一个<i>强壮</i>的男人。</p>

</body>
</html>

CSS - :lang 伪类

:lang 伪类允许您为不同的语言定义特殊的规则。

在下面的例子中,:lang 为属性为 lang=”en” 的 元素定义引号:

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<style>
q:lang(en) {
quotes: "~" "~";
}
</style>
</head>
<body>

<p>Some text <q lang="en">A quote in a paragraph</q> Some text.</p>

<p>在本例中,:lang 为 lang="en" 的 q 元素定义引号:</p>

</body>
</html>

结果

1
2
3
Some text~A quote in a paragraph~Some text.

在本例中,:lang 为 lang="en" 的 q 元素定义引号:

所有 CSS 伪类

选择器 例子 例子描述
:active a:active 选择活动的链接。
:checked input:checked 选择每个被选中的 元素。
:disabled input:disabled 选择每个被禁用的 元素。
:empty p:empty 选择没有子元素的每个

元素。

:enabled input:enabled 选择每个已启用的 元素。
:first-child p:first-child 选择作为其父的首个子元素的每个

元素。

:first-of-type p:first-of-type 选择作为其父的首个

元素的每个

元素。

:focus input:focus 选择获得焦点的 元素。
:hover a:hover 选择鼠标悬停其上的链接。
:in-range input:in-range 选择具有指定范围内的值的 元素。
:invalid input:invalid 选择所有具有无效值的 元素。
:lang(language) p:lang(it) 选择每个 lang 属性值以 “it” 开头的

元素。

:last-child p:last-child 选择作为其父的最后一个子元素的每个

元素。

:last-of-type p:last-of-type 选择作为其父的最后一个

元素的每个

元素。

:link a:link 选择所有未被访问的链接。
:not(selector) :not(p) 选择每个非

元素的元素。

:nth-child(n) p:nth-child(2) 选择作为其父的第二个子元素的每个

元素。

:nth-last-child(n) p:nth-last-child(2) 选择作为父的第二个子元素的每个

元素,从最后一个子元素计数。

:nth-last-of-type(n) p:nth-last-of-type(2) 选择作为父的第二个

元素的每个

元素,从最后一个子元素计数

:nth-of-type(n) p:nth-of-type(2) 选择作为其父的第二个

元素的每个

元素。

:only-of-type p:only-of-type 选择作为其父的唯一

元素的每个

元素。

:only-child p:only-child 选择作为其父的唯一子元素的

元素。

:optional input:optional 选择不带 “required” 属性的 元素。
:out-of-range input:out-of-range 选择值在指定范围之外的 元素。
:read-only input:read-only 选择指定了 “readonly” 属性的 元素。
:read-write input:read-write 选择不带 “readonly” 属性的 元素。
:required input:required 选择指定了 “required” 属性的 元素。
:root root 选择元素的根元素。
:target #news:target 选择当前活动的 #news 元素(单击包含该锚名称的 URL)。
:valid input:valid 选择所有具有有效值的 元素。
:visited a:visited 选择所有已访问的链接。

所有 CSS 伪元素

选择器 例子 例子描述
::after p::after 在每个

元素之后插入内容。

::before p::before 在每个

元素之前插入内容。

::first-letter p::first-letter 选择每个

元素的首字母。

::first-line p::first-line 选择每个

元素的首行。

::selection p::selection 选择用户选择的元素部分

伪元素

什么是伪元素?

CSS 伪元素用于设置元素指定部分的样式。

例如,它可用于:

  • 设置元素的首字母、首行的样式
  • 在元素的内容之前或之后插入内容

伪元素的语法:

1
selector::pseudo-element {property:value;}

CSS类也可以使用伪元素:

1
selector.class::pseudo-element {property:value;}

::first-line 伪元素

::first-line 伪元素用于向文本的首行添加特殊样式。

下面的例子为所有

元素中的首行添加样式:

实例

1
2
3
4
p::first-line {
color: #ff0000;
font-variant: small-caps;
}

注意:::first-line 伪元素只能应用于块级元素。

以下属性适用于 ::first-line 伪元素:

  • 字体属性
  • 颜色属性
  • 背景属性
  • word-spacing
  • letter-spacing
  • text-decoration
  • vertical-align
  • text-transform
  • line-height
  • clear

请注意双冒号表示法 - ::first-line 对比 :first-line

在 CSS3 中,双冒号取代了伪元素的单冒号表示法。这是 W3C 试图区分伪类伪元素的尝试。

在 CSS2 和 CSS1 中,伪类和伪元素都使用了单冒号语法。

为了向后兼容,CSS2 和 CSS1 伪元素可接受单冒号语法。

::first-letter 伪元素

::first-letter 伪元素用于向文本的首字母添加特殊样式。

下面的例子设置所有

元素中文本的首字母格式:

实例

1
2
3
4
p::first-letter {
color: #ff0000;
font-size: xx-large;
}

伪元素和 CSS 类

伪元素可以与 CSS 类结合使用:

实例

1
2
3
4
p.intro::first-letter {
color: #ff0000;
font-size: 200%;
}

上面的例子将以红色和较大的字体显示 class=”intro” 的段落的首字母。

多个伪元素

也可以组合几个伪元素。

在下面的例子中,段落的第一个字母将是红色,字体大小为 xx-large。第一行的其余部分将变为蓝色,并使用小型大写字母。该段的其余部分将是默认的字体大小和颜色:

实例

1
2
3
4
5
6
7
8
9
p::first-letter {
color: #ff0000;
font-size: xx-large;
}

p::first-line {
color: #0000ff;
font-variant: small-caps;
}

CSS - ::before 伪元素

::before 伪元素可用于在元素内容之前插入一些内容。

下面的例子在每个 <h1> 元素的内容之前插入一幅图像:

实例

1
2
3
h1::before {
content: url(smiley.gif);
}

CSS - ::after 伪元素

::after 伪元素可用于在元素内容之后插入一些内容。

下面的例子在每个<h1> 元素的内容之后插入一幅图像:

实例

1
2
3
h1::after {
content: url(smiley.gif);
}

CSS - ::selection 伪元素

::selection 伪元素匹配用户选择的元素部分。

以下 CSS 属性可以应用于 ::selection

  • color
  • background
  • cursor
  • outline

下例使所选文本在黄色背景上显示为红色:

实例

1
2
3
4
::selection {
color: red;
background: yellow;
}

所有 CSS 伪元素

选择器 例子 例子描述
::after p::after 在每个

元素之后插入内容。

::before p::before 在每个

元素之前插入内容。

::first-letter p::first-letter 选择每个

元素的首字母。

::first-line p::first-line 选择每个

元素的首行。

::selection p::selection 选择用户选择的元素部分。

所有 CSS 伪类

选择器 例子 例子描述
:active a:active 选择活动的链接。
:checked input:checked 选择每个被选中的 元素。
:disabled input:disabled 选择每个被禁用的 元素。
:empty p:empty 选择没有子元素的每个

元素。

:enabled input:enabled 选择每个已启用的 元素。
:first-child p:first-child 选择作为其父的首个子元素的每个

元素。

:first-of-type p:first-of-type 选择作为其父的首个

元素的每个

元素。

:focus input:focus 选择获得焦点的 元素。
:hover a:hover 选择鼠标悬停其上的链接。
:in-range input:in-range 选择具有指定范围内的值的 元素。
:invalid input:invalid 选择所有具有无效值的 元素。
:lang(language) p:lang(it) 选择每个 lang 属性值以 “it” 开头的

元素。

:last-child p:last-child 选择作为其父的最后一个子元素的每个

元素。

:last-of-type p:last-of-type 选择作为其父的最后一个

元素的每个

元素。

:link a:link 选择所有未被访问的链接。
:not(selector) :not(p) 选择每个非

元素的元素。

:nth-child(n) p:nth-child(2) 选择作为其父的第二个子元素的每个

元素。

:nth-last-child(n) p:nth-last-child(2) 选择作为父的第二个子元素的每个

元素,从最后一个子元素计数。

:nth-last-of-type(n) p:nth-last-of-type(2) 选择作为父的第二个

元素的每个

元素,从最后一个子元素计数

:nth-of-type(n) p:nth-of-type(2) 选择作为其父的第二个

元素的每个

元素。

:only-of-type p:only-of-type 选择作为其父的唯一

元素的每个

元素。

:only-child p:only-child 选择作为其父的唯一子元素的

元素。

:optional input:optional 选择不带 “required” 属性的 元素。
:out-of-range input:out-of-range 选择值在指定范围之外的 元素。
:read-only input:read-only 选择指定了 “readonly” 属性的 元素。
:read-write input:read-write 选择不带 “readonly” 属性的 元素。
:required input:required 选择指定了 “required” 属性的 元素。
:root root 选择元素的根元素。
:target #news:target 选择当前活动的 #news 元素(单击包含该锚名称的 URL)。
:valid input:valid 选择所有具有有效值的 元素。
:visited a:visited 选择所有已访问的链接。

属性选择器(CSS3新增)

属性选择器是基于属性来定位一个元素。可以指定该元素的某个属性,这样所有使用该属性的元素都将被定位。

属性选择器有如下五种:(CSS3新增三个)

所有 CSS 属性选择器

属性名称 含义
[att^=”value”] 该属性的值以指定的值开始 (新增)
[att$=”value”] 该属性的值以指定的值结束 (新增)
[att*=”value”] 该属性的值包含指定的值,无论其位置 (新增)
[att~=”value”] 该属性的值包含指定的值(value为完整单词)
[att|=”value”] 该属性的值必须为指定的值(或者以 - 分隔开)
选择器 例子 例子描述
[attribute] [target] 选择带有 target 属性的所有元素。
[attribute=value] [target=_blank] 选择带有 target=”_blank” 属性的所有元素。
[attribute~=value] [title~=flower] 选择带有包含 “flower” 一词的 title 属性的所有元素。
[attribute|=value] [lang|=en] 选择带有以 “en” 开头的 lang 属性的所有元素。
[attribute^=value] a[href^=”https”] 选择其 href 属性值以 “https” 开头的每个 元素。
[attribute$=value] a[href$=”.pdf”] 选择其 href 属性值以 “.pdf” 结尾的每个 元素。
[attribute*=value] a[href*=”w3school”] 选择其 href 属性值包含子串 “w3school” 的每个 元素。

CSS [attribute] 选择器

[attribute] 选择器用于选取带有指定属性的元素。

下例选择所有带有 target 属性的 元素;

实例

1
2
3
a[target] {
background-color: yellow;
}

CSS [attribute=”value”] 选择器

[attribute=”value”] 选择器用于选取带有指定属性和值的元素。

下例选取所有带有 target=”_blank” 属性的 元素:

实例

1
2
3
a[target="_blank"] { 
background-color: yellow;
}

CSS [attribute~=”value”] 选择器

[attribute~=”value”] 选择器选取属性值包含指定词的元素。

下例选取 title 属性包含 “flower” 单词的所有元素:

实例

1
2
3
[title~="flower"] {
border: 5px solid yellow;
}

上面的例子会匹配以下属性的元素:title=”flower”、title=”summer flower” 以及 title=”flower new”,但不匹配:title=”my-flower” 或 title=”flowers”。

CSS [attribute|=”value”] 选择器

[attribute|=”value”] 选择器用于选取指定属性以指定值开头的元素。

下例选取 class 属性以 “top” 开头的所有元素:

注释:值必须是完整或单独的单词,比如 class=”top” 或者后跟连字符的,比如 class=”top-text”。

1
2
3
[class|="top"] {
background: yellow;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<style>
[class|=top] {
background: yellow;
}
</style>
</head>
<body>

<h1>CSS [attribute|="value"] 选择器</h1>

<h1 class="top-header">Welcome</h1>//有效果
<p class="top-text">Hello world!</p>//有效果
<p class="topcontent">Are you learning CSS?</p>//无效果

</body>
</html>

CSS [attribute^=”value”] 选择器

[attribute^=”value”] 选择器用于选取指定属性以指定值开头的元素。

下例选取 class 属性以 “top” 开头的所有元素:

提示:值不必是完整单词!

1
2
3
[class^="top"] {
background: yellow;
}

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<style>
[class^="top"] {
background: yellow;
}
</style>
</head>
<body>

<h1>CSS [attribute^="value"] 选择器</h1>

<h1 class="top-header">Welcome</h1>//有效果
<p class="top-text">Hello world!</p>//有效果
<p class="topcontent">Are you learning CSS?</p>//有效果

</body>
</html>

CSS [attribute$=”value”] 选择器

[attribute$=”value”] 选择器用于选取指定属性以指定值结尾的元素。

下例选取 class 属性以 “test” 结尾的所有元素:

提示:值不必是完整单词!

实例

1
2
3
[class$="test"] {
background: yellow;
}

CSS [attribute*=”value”] 选择器

[attribute*=”value”] 选择器选取属性值包含指定词的元素。

下例选取 class 属性包含 “te” 的所有元素:

提示:值不必是完整单词!

实例

1
2
3
[class*="te"] {
background: yellow;
}

设置表单样式

若需为不带 class 或 id 的表单设置样式,属性选择器会很有用:

实例

1
2
3
4
5
6
7
8
9
10
11
12
input[type="text"] {
width: 150px;
display: block;
margin-bottom: 10px;
background-color: yellow;
}

input[type="button"] {
width: 120px;
margin-left: 35px;
display: block;
}

浅谈JavaScript中的闭包

简述闭包

谈及闭包,每个人都有不同的理解,“一千个读者眼中就会有一千个哈姆雷特。”。笔者认为,简述闭包就是,让开发者可以从内部函数访问外部函数的作用域,即使在父函数关闭之后。

实例

1
2
3
4
5
6
7
8
9
10
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();

add();
add();
add();

// 计数器目前是 3

看明白了吗?如果没有的话,让我们重头来过。

解释引例1

全局变量

我们知道,在JavaScript中,函数能够访问内部定义的所有变量:

1
2
3
4
function myFunction() {
var a = 4;
return a * a;
}

也能够访问函数外部定义的变量:

1
2
3
4
var a = 4;
function myFunction() {
return a * a;
}

在最后这个例子中,a全局变量。

在网页中,全局变量属于 window 对象。

全局变量能够被页面中(以及窗口中)的所有脚本使用和修改。

在第一个例子中,a局部变量。

局部变量只能用于其被定义的函数内部。对于其他函数和脚本代码来说它是不可见的。

拥有相同名称的全局变量和局部变量是不同的变量。修改一个,不会改变其他。

不通过关键词 var 创建的变量总是全局的,即使它们在函数中创建(即变量提升)。

1
2
3
function A(){
x = 5;
}

此时,x相当于全局变量。


变量的生命周期

全局变量活得和您的应用程序(窗口、网页)一样久。

局部变量活得不长。它们在函数调用时创建,在函数完成后被删除。


解释引例2

假设您想使用变量来计数,并且您希望此计数器可用于所有函数。

您可以使用全局变量和函数来递增计数器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 初始化计数器
var counter = 0;

// 递增计数器的函数
function add() {
counter += 1;
}

// 调用三次 add()
add();
add();
add();

// 此时计数器应该是 3

但是这个计数器存在一些问题,我们可以通过其他方式改变counter的值不一定需要通过add()方法,又或者说,这个全局变量counter会受到其他函数或者方法的影响而改变,这时我add()方法统计出来的counter的值,可能不是正确的结果,为了解决这个问题,我们把变量定义移到add()方法内部:

1
2
3
4
5
6
7
8
9
10
11
12
// 递增计数器的函数
function add() {
var counter = 0;
counter += 1;
}

// 调用三次 add()
add();
add();
add();

//此时计数器应该是 3。但它是 1。

此时counter为方法内的局部变量,不会受到其他函数或者方法的影响,但是,我们发现,实际上,输出的并不是我们想要的结果。因为每一次执行add方法时,counter都会被置0。

实际上我们想要的结果是:在开始时,counter初始化为0,此后不再执行置0操作,但是每次都会执行+1操作。那怎么办呢?我们可以这样实现:

1
2
3
4
5
6
7
8
9
10
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();

add();//第一次调用 counter值为1
add();//第二次调用 counter值为2
add();//第三次调用 counter值为3

// 计数器目前是 3

我们定义了一个add变量,让它等于一个自调用函数:

1
(function(){})() //自调用函数格式

那么我们来解释一下,上述代码片段:

第一次调用add方法时,会按照从上到下执行,counter初始化为0,然后counter = counter + 1,所以第一次结果输出为1

第二次调用add方法,注意这里因为第一次调用时返回给我们的是return function () {return counter += 1;}所以此时实际上add长这样:

1
add =function () {return counter += 1; } //couter值为1

因为我们并没有去执行第一个匿名函数,所以counter值并没有置0,仍然为我们之前改变的1

此时counter = counter(1) + 1为2

第三次也可以这么理解。

上述代码片段也可以改写成:

1
2
3
4
5
6
7
8
9
10
11
12
function counter() {
let counter = 0;
return function incrementCount() {
return counter += 1;
}
}

const add = counter();
add(); // 输出 1
add(); // 输出 2
add(); // 输出 3

总结

我们通过计数器的例子,实实在在的访问并改变了外部函数的变量,除了第一次调用过这个函数之外。后续的每一次变量的访问和改变我们都没有访问外部函数。这就是闭包的经典案列。