Web编程学习笔记3:JS入门
本笔记主要依据MDN Web Docs:https://developer.mozilla.org/zh-CN/
基本语法
JavaScript 是一种轻量级的动态类型解释型语言。JS 语法风格类似于 C 语言家族:
- 分号:语句以分号
;
结尾(可选,但推荐使用) - 花括号:代码块用
{}
包裹 - 控制结构:
if
、else
、for
、while
、switch
等与 C 语言几乎一致 - 运算符和 C 语言家族几乎完全一样
但是特性类似于 Python:
- 用
function
关键字定义函数 - 动态类型
- 数组和对象用法类似于 Py
- 支持将函数作为参数,或者把函数作为返回值
变量声明
JavaScript 使用 var
、let
或 const
来声明变量:
var
:函数作用域,传统方式(不推荐使用)let
:块级作用域,可以重新赋值const
:块级作用域,声明后不能重新赋值(常量)
块级作用域:一个
{}
包裹的区域有效函数作用域:在一个函数里就有效:
1
2
3
4
5
6
7
8
function example() {
if (true) {
var x = 10; // 函数作用域变量
}
console.log(x); // 输出 10
}
example();
console.log(x); // 报错:x is not defined
1 |
|
另外,变量可以在没有 let
、const
或 var
声明的情况下直接使用,但这会导致变量成为全局变量(在非严格模式下),或者报错(在严格模式下)。这种行为通常是不推荐的,因为它可能导致意外的全局变量污染和难以调试的问题。
严格模式(Strict Mode)和非严格模式(Sloppy Mode)是 JavaScript 的两种运行模式。严格模式是 ES5(ECMAScript 5)引入的特性,旨在帮助开发者避免一些常见的错误和不规范的写法。
在脚本或函数的顶部添加
"use strict";
即可启用严格模式。
1
2
"use strict"; // 启用严格模式
x = 10; // 报错:x is not defined
1
2
3
4
function strictFunction() {
"use strict"; // 局部严格模式
y = 20; // 报错:y is not defined
}在严格模式下,使用未声明的变量、删除(
delete
)变量,以及**在函数参数中使用两个名字一样的变量(比如function example(a,a)
)**等方面都会报错。
数据类型
JavaScript 是动态类型语言,常见的数据类型包括:
- 基本类型:
string
、number
、boolean
、null
、undefined
、symbol
。 - 引用类型:
object
、array
、function
。
1 |
|
运算符
- 算术运算符:
+
、-
、*
、/
、%
。 - 比较运算符:
==
、===
、!=
、!==
、>
、<
。 - 逻辑运算符:
&&
、||
、!
。
1 |
|
==
和===
的区别主要在于是否为严格相等。前者在比较的时候会进行隐式类型转换,并且会运用valueOf
或者toString
等方法。所以更推荐使用===
和!==
。
条件语句
if...else
:根据条件执行代码。switch
:多条件分支。
1 |
|
循环
for
:遍历数组或执行固定次数的循环。while
:条件为真时执行循环。for...of
:遍历可迭代对象(如数组)
1 |
|
函数
函数是 JavaScript 的核心,用于封装可重复使用的代码。
1 |
|
默认参数
在参数名称后添加 = 默认值
,来指定默认值:
1 |
|
匿名函数和箭头函数
把函数作为参数传递时,可以使用匿名函数,例如:
1 |
|
也可以用 (event) =>
来代替 function(event)
:
1 |
|
如果函数只含有一个参数,那就可以省略掉括号:
1 |
|
最终,如果函数只包含一行return
语句,那就可以省略到只剩下参数 => 返回值
:
1 |
|
或
1 |
|
事件
本节主要参考[1]
事件是系统遇到的一些事情,在这个时候,系统会产生某种信号,并可以自动地采取某种行动(即运行一些代码)。
为了对一个事件做出反应,你要给它附加一个事件处理器(通常是创建的一个 JavaScript 函数),在事件发生时运行。当这样一个代码块被定义为响应一个事件而运行时,称为注册一个事件处理器。事件处理器有时候被叫做事件监听器——从我们的用意来看这两个名字是相同的,尽管严格地来说这块代码既监听也处理事件。监听器留意事件是否发生,处理器对事件发生做出回应。
事件处理
HTML 事件属性
直接在 HTML 元素中定义事件处理程序。
1 |
|
DOM 属性
通过 JavaScript 为元素的属性赋值来绑定事件处理程序。
1 |
|
addEventListener
推荐的方式,可以为同一个事件绑定多个处理程序。
1 |
|
阻止默认行为
有时会遇到一些情况:希望事件不执行它的默认行为。这个时候就可以在事件对象上使用preventDefault()
方法,停止默认行为,例如:
1 |
|
1 |
|
事件冒泡
本节主要参考[2]
事件冒泡指的是,对于嵌套元素的事件,浏览器要如何处理它。例如:
1 |
|
这个 HTML 语句中,button
是嵌套在div
中的,div
又嵌套在body
里,那么如果绑定一个 JS :
1 |
|
它的输出是:
你在 BUTTON 元素上进行了点击
你在 DIV 元素上进行了点击
你在 BODY 元素上进行了点击
那是因为它们互相嵌套,按了按钮以后,肯定div
也被按了,body
也是。但是button
最先被监听到,就好像从最里面冒泡出来,所以叫事件冒泡。
显然,事件冒泡可能会造成一些很奇怪的问题,那么就可以用event.stopPropagation()
修复,防止事件向其他元素传递。
事件捕获
事件冒泡是从里向外的,捕获就是从外向里的。事件捕获默认是关闭的,可以在addEventListener()
的 capture
选项中启用。例如:
1 |
|
1 |
|
它的输出会是:
你在 BODY 元素上进行了点击
你在 DIV 元素上进行了点击
你在 BUTTON 元素上进行了点击
可以看到完全颠倒过来了。
为什么要同时使用捕获和冒泡功能?在过去的坏日子里,当浏览器的交叉兼容性远不如现在时,Netscape 只使用事件捕捉,而 Internet Explorer 只使用事件冒泡。当 W3C 决定尝试将行为标准化并达成共识时,他们最终确定了这个包括这两种行为的系统,这也是现代浏览器所实现的。
默认情况下,几乎所有的事件处理程序都是在冒泡阶段注册的,这在大多数情况下更有意义。
事件委托
如果想在用户与大量的子元素中的任何一个互动时运行一些代码时,我们在它们的父元素上设置事件监听器,让发生在它们身上的事件冒泡到它们的父元素上,而不必在每个子元素上单独设置事件监听器。这叫做事件委托。
例如:
- Item 1
- Item 2
- Item 3
1 |
|
事件的基本属性:
event.type
:事件的类型(如click
、keydown
、mouseover
等),例如:
1
2
3
button.addEventListener("click", function(event) {
console.log(event.type); // 输出 "click"
});
event.target
:触发事件的元素(即事件的目标元素),例如:
1
2
3
button.addEventListener("click", function(event) {
console.log(event.target); // 输出触发事件的按钮元素
});
event.currentTarget
:当前正在处理事件的元素(可能与event.target
不同,尤其是在事件冒泡阶段),例如:
1
2
3
div.addEventListener("click", function(event) {
console.log(event.currentTarget); // 输出绑定事件的 div 元素
});
event.bubbles
:表示事件是否冒泡,例如:
1
2
3
button.addEventListener("click", function(event) {
console.log(event.bubbles); // 输出 true(click 事件会冒泡)
});
event.preventDefault()
:阻止事件的默认行为(如表单提交、链接跳转),例如:
1
2
3
link.addEventListener("click", function(event) {
event.preventDefault(); // 阻止链接跳转
});
event.stopPropagation()
:阻止事件继续传播(捕获或冒泡),例如
1
2
3
button.addEventListener("click", function(event) {
event.stopPropagation(); // 阻止事件冒泡
});