层次 | 作用 |
---|---|
HTML(结构层) | 利用语义化标签搭建网页 |
CSS(样式层) | 利用样式进行美化网页、进行网页布局 |
JavaScript(行为层) | 可以给网页添加动态效果 |
JavaScript 是一种高级、解释型的编程语言,由网景公司(Netscape)在1995年开发,现由ECMA国际通过ECMAScript标准规范进行标准化。它是互联网上最广泛使用的客户端脚本语言,主要用于增强网页和用户交互、构建动态功能及创建网络应用。JavaScript 最初设计用于嵌入到HTML文档中,并能在用户的浏览器端直接执行,无需编译成可执行文件。随着技术发展,JavaScript 也扩展到了服务器端(Node.js)、移动端应用开发(如React Native)以及跨平台桌面应用开发(Electron)等领域。JavaScript 在Web开发中的核心作用包括表单验证、动画效果、用户界面互动、数据处理以及构建复杂的单页应用程序(SPA)等。此外,它还支持大量的开源库和框架,如jQuery、React、Vue.js等,极大地丰富了其功能和使用场景。
JavaScript的组成
另外,在现代Web开发中,还有其他一些重要组成部分,如:
JavaScript 的主要特点包括:
JavaScript输出数据的方式:
window.alert()
弹出警告框。document.write()
方法将内容写到 HTML 文档中。innerHTML
写入到 HTML 元素。console.log()
写入到浏览器的控制台。prompt()
是一个内置的浏览器窗口对象方法,用于与用户进行交互。它会弹出一个对话框,显示一段提示信息,并允许用户输入文本数据。数据类型:
number
(数字)、string
(字符串)、boolean
(布尔值)、null
、undefined
以及ES6新增的symbol
。object
(对象)和function
(函数),其中数组(array
)和正则表达式(RegExp
)也是对象类型的子类。变量声明:
var
:在ES5及更早版本中使用,具有变量提升特性,在同一个作用域内可以重新声明。let
和 const
(ES6引入):提供了块级作用域,并且const
用于声明常量,一旦赋值后不可更改其引用。操作符:
+
、-
、*
、/
、%
等。>
、<
、>=
、<=
、==
、!=
、===
(严格相等)、!==
(严格不等)。&&
(逻辑与)、||
(逻辑或)、!
(逻辑非)。=
, +=
, -=
等。&
、|
、^
、~
、<<
、>>
、>>>
。condition ? exprIfTrue : exprIfFalse
。控制结构:
if...else
、switch
。for
、while
、do...while
、for...in
(遍历对象属性)、for...of
(遍历可迭代对象,如数组)。break
、continue
。函数:
function
关键字创建函数。(param1, param2) => expression
或 { statements }
。return
语句从函数内部返回结果。对象:
{ key: value }
。.
或[ ]
来访问和修改对象属性。new
关键字实例化对象。数组:
[]
初始化数组。.push()
、.pop()
、.shift()
、.unshift()
、.slice()
、.map()
、.filter()
等。字符串:
.length
获取长度、.charAt()
访问单个字符、.split()
分割字符串、.concat()
拼接字符串等。内置对象包括Math
、Date
、Array
、Object
、Function
、RegExp
等。
Object
:所有JavaScript对象的基类,提供了一些通用的方法:
Object.create(prototype[, propertiesObject])
:创建一个新对象,其[[Prototype]]链接到指定的对象。Object.defineProperty(obj, prop, descriptor)
:直接在一个对象上定义或修改一个属性及其特性。Object.keys(obj)
、Object.values(obj)
和Object.entries(obj)
:分别返回一个对象的所有自身可枚举属性名数组、值数组和键值对数组。Array
:数组对象的构造函数,包含大量处理数组的方法:
push()
: 向数组末尾添加元素。pop()
: 删除并返回数组最后一个元素。shift()
: 删除并返回数组的第一个元素。unshift()
: 在数组开头添加元素。slice()
: 返回一个子数组,原数组不变。map()
: 创建一个新数组,其结果是调用提供的函数处理原数组每个元素的结果。filter()
: 创建一个新数组,其中包含通过测试函数的所有元素。Function`
Function
的实例,拥有自己的方法如call()
、apply()
和bind()
用于改变函数上下文(this)并执行函数。String
:字符串对象的相关方法:
length
: 属性返回字符串的长度。charAt(index)
: 返回指定位置的字符。substring(start, end?)
: 提取字符串的一部分。split(separator[, limit])
: 根据分隔符将字符串分割成数组。concat(string2, ...[, stringN])
: 连接两个或更多的字符串,并返回一个新的字符串。Number
:提供与数字相关的属性和方法,例如:
isNaN(value)
: 判断给定参数是否为NaN。isFinite(number)
: 判断给定数是否为有限数值。toFixed(digits)
: 把数字转换为指定位数的小数。Math
:包含数学常数和函数,如:
Math.PI
: 圆周率。Math.random()
: 返回0到1之间的随机浮点数。Math.floor(x)
: 对数进行下舍入。Math.ceil(x)
: 对数进行上舍入。Math.pow(base, exponent)
: 计算基数的指数次幂。Date
:表示日期和时间的JavaScript对象,可以获取当前日期、设置日期以及进行日期操作。
创建Date对象:
构造函数:
var date = new Date();
不传入参数时,创建的是当前时间的一个新实例。
或者可以通过以下方式指定特定时间:
// 直接输入年、月、日等参数(月份从0开始计数,因此1代表2月)
var date1 = new Date(2024, 0, 18); // 创建一个2024年1月18日的新实例
// 使用特定格式的字符串创建
var date2 = new Date("January 18, 2024 00:00:00");
var date3 = new Date("2024-01-18T00:00:00"); // ISO 8601格式
// 指定自1970年1月1日以来的毫秒数
var date4 = new Date(1685055600000); // 2023年8月2日12:00:00 UTC
获取和设置日期/时间值:
实例方法
:
getDate()
, getDay()
, getFullYear()
, getHours()
, getMilliseconds()
, getMinutes()
, getMonth()
, getSeconds()
, getTime()
, getTimezoneOffset()
等用于获取相应的时间部分。setDate()
, setFullYear()
, setHours()
, setMilliseconds()
, setMinutes()
, setMonth()
, setSeconds()
等方法来设置具体的时间值。示例:
var today = new Date();
console.log(today.getDate()); // 获取当前日期(1-31)
today.setFullYear(2025); // 设置年份为2025
其他常用方法:
toLocaleDateString()
和 toLocaleTimeString()
方法将日期和时间转换为本地化格式的字符串。toDateString()
返回日期部分的字符串形式。toTimeString()
返回时间部分的字符串形式。toISOString()
返回ISO 8601格式的字符串,如:“2024-01-18T00:00:00.000Z”。静态方法:
Date.now()
返回当前时间距离1970年1月1日0点0分0秒(UTC)的毫秒数。Date.parse(dateString)
解析给定的日期字符串,并返回该时间点与1970年1月1日之间的毫秒数。此方法对于不同格式的日期字符串解析规则可能因浏览器而异,建议使用new Date(dateString)
并检查返回值是否有效来确保兼容性。示例操作:
var d = new Date();
console.log(d.toLocaleString()); // 显示当前日期和时间的本地格式
d.setDate(d.getDate() + 7); // 将日期增加7天
console.log(d.toDateString()); // 显示修改后日期
console.log(Date.now()); // 输出当前时间戳(毫秒)
RegExp
:正则表达式(Regular Expression,简称 RegExp),是 JavaScript 中用于处理文本字符串的强大工具。它定义了一种模式,可以用来搜索、匹配、替换文本中的特定子串。
在JavaScript中创建正则表达式有两种方式:
字面量语法:
var regex = /pattern/flags;
其中 pattern
是一个代表所需匹配模式的字符串,而 flags
可选,包含标志字符(如 g、i、m),分别表示全局搜索(global)、不区分大小写(ignore case)和多行模式(multiline)。
构造函数语法:
var regex = new RegExp('pattern', 'flags');
正则表达式的常用方法:
.test(string)
: 测试给定字符串是否满足正则表达式所定义的模式。.exec(string)
: 在字符串中执行查找,并返回第一个匹配项的信息,如果没有找到匹配项,则返回null
。当使用全局标志g
时,连续调用.exec()
会逐个查找所有匹配项。与字符串对象结合的方法:
string.match(regexp)
: 在字符串中查找正则表达式的匹配项,返回匹配结果数组或null
。string.replace(regexp|substr, newSubstr|function)
:根据正则表达式或子串进行查找并替换,如果第一个参数是正则表达式还可以利用分组(()
)捕获的内容进行动态替换。string.search(regexp)
:返回字符串中第一次出现正则表达式匹配项的索引位置,如果没有找到返回-1
。全局函数如isNaN()
检查是否为NaN、parseInt()
和parseFloat()
转换字符串为数字、prompt()
、alert()
、confirm()
与用户交互。
isNaN(value)
: 这不是一个正则表达式相关函数,而是用来检查传递的值是否为NaN(非数字)。返回值是一个布尔值,如果是NaN则返回true
,否则返回false
。parseInt(string, radix)
: 该函数解析一个字符串,并返回一个整数。第二个可选参数指定进制,默认是10进制。如果字符串不能被解析成有效的整数,或者基数无效,则返回NaN
。parseFloat(string)
: 类似于parseInt
,但此函数尝试将字符串解析为浮点数。prompt(message[, defaultText])
: 此全局浏览器函数弹出一个对话框,提示用户输入信息。返回用户输入的字符串或在用户取消时返回null
。alert(message)
: 显示一个警告对话框,包含指定的消息内容,并在用户点击确定后关闭。confirm(question)
: 显示一个确认对话框,包含指定的问题文本以及“确定”和“取消”按钮。用户点击确定时返回true
,点击取消时返回false
。全局函数部分在JavaScript中指的是可以直接调用而无需特定对象的函数,这些函数在浏览器环境中提供了一些基本的用户交互和数据处理能力。以下是几个常用的全局函数详细介绍:
isNaN(value)
var num = "Hello";
console.log(isNaN(num)); // 输出:true,因为"Hello"不是数字
注意:isNaN
会首先尝试将传入值转换为数字,因此某些非数字字符串也可能返回false,例如空字符串""会被转换为0,所以isNaN("")
会返回false。
parseInt(string, radix)
var str = "123";
console.log(parseInt(str)); // 输出:123
console.log(parseInt("1101", 2)); // 输出:13,二进制数1101转换为十进制数
parseFloat(string)
parseInt
,但此函数尝试将字符串解析为浮点数。var floatStr = "3.14";
console.log(parseFloat(floatStr)); // 输出:3.14
prompt(message[, defaultText])
null
。var userInput = prompt("请输入您的姓名:", "John Doe");
if (userInput !== null) {
console.log(userInput);
}
alert(message)
alert("这是一条消息提醒!");
confirm(question)
true
;点击“取消”时,函数返回false
。var isAgreed = confirm("你是否同意条款和条件?");
if (isAgreed) {
console.log("用户已同意条款和条件");
} else {
console.log("用户不同意条款和条件");
}
这些全局函数主要用于简单的用户交互和数据类型转换,在现代Web应用开发中,为了更好的用户体验,推荐使用更复杂的UI组件和API进行交互操作。对于验证数据格式等任务,正则表达式也经常与这些函数结合使用。
异步编程
在JavaScript中,由于其单线程执行模型,处理网络请求、文件读写等耗时操作时需要采用异步编程方式,以避免阻塞主线程。以下是关于异步编程的三种主要技术手段的详细解释:
回调函数 回调函数是最早的异步编程模式之一,在JavaScript中广泛应用。当一个异步任务完成后,通过调用预先定义好的函数(即回调函数)来处理结果或错误。
function getData(callback) {
// 假设这是一个异步操作
setTimeout(() => {
const data = 'Async Data';
callback(data); // 异步操作完成后调用回调函数
}, 2000);
}
function processData(data) {
console.log('Processed data:', data);
}
// 使用回调函数处理异步结果
getData(processData);
缺点:随着异步逻辑复杂度增加,多个回调嵌套导致代码难以阅读和维护,这通常被称为“回调地狱”。
Promise Promise 是ES6引入的一种标准机制,用于处理异步操作并解决回调地狱问题。它代表了一个异步操作的最终完成(或失败)及其结果值。Promise有三种状态:pending(进行中)、fulfilled(已成功)或rejected(已失败)。一旦状态改变,就不可再变。
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Async Data';
if (data) { // 模拟异步操作的成功情况
resolve(data);
} else {
reject(new Error('Failed to fetch data'));
}
}, 2000);
});
}
getData().then(data => {
console.log('Processed data:', data);
}).catch(error => {
console.error('Error:', error.message);
});
async/await async/await 是基于Promise的更简洁的异步编程语法糖。async
关键字用来声明一个异步函数,该函数会隐式地返回一个Promise对象;await
关键字则用于等待Promise的结果,并可以放在async
函数内部。
async function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Async Data');
}, 2000);
});
}
async function main() {
try {
const data = await getData();
console.log('Processed data:', data);
} catch (error) {
console.error('Error:', error.message);
}
}
main(); // 启动异步操作
使用async/await可以使异步代码看起来更加同步化,更易于理解和调试。然而,本质上它们仍然是基于Promise的异步编程机制,只是提供了一种更接近传统顺序流程控制的语法形式。
模块化
是编程中的一种设计思想,它将程序分割成多个独立、可复用的部分(即模块),每个模块有自己明确的职责和接口。在JavaScript中,ES6引入了原生的模块系统,通过import
和export
关键字支持模块导入导出功能,使得代码结构更加清晰,同时方便代码复用和管理。
export
关键字:export
用于对外暴露模块的功能(变量、函数、类等)。一个模块可以有多个export语句,也可以通过default export来指定一个默认输出项。
命名导出:为模块内的每个需要导出的成员分别指定名称
// math.js
function add(x, y) {
return x + y;
}
function subtract(x, y) {
return x - y;
}
export { add, subtract };
默认导出:模块内只能有一个default export,代表这个模块的默认出口。
// person.js
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
export default Person;
import
关键字:import
用于从其他模块导入已经导出的功能。
导入默认导出:
// 导入person.js中的默认导出(Person类)
import Person from './person';
const alice = new Person('Alice', 30);
导入命名导出:
// 导入math.js中的命名导出
import { add, subtract } from './math';
console.log(add(5, 3)); // 输出8
console.log(subtract(5, 3)); // 输出2
重命名导入:导入时可以给导入的变量或函数重新命名以避免命名冲突
import { add as sum, subtract as difference } from './math';
整体导入:使用*
一次性导入模块的所有导出项目,并将其作为一个对象来访问
// 导入math.js的所有导出内容
import * as math from './math';
console.log(math.add(5, 3)); // 输出8
console.log(math.subtract(5, 3)); // 输出2
通过这种方式,JavaScript开发者可以在不同的文件中编写模块化的代码,然后通过import
和export
相互连接,形成一个复杂的、分层次的应用程序结构。