一、JavaScript基本概念
JavaScript的定义与历史
JavaScript(简称JS)是一种高级的、解释型的、多范式的编程语言。它最初是为网页添加交互性而设计的,但现在也广泛用于服务器端开发(Node.js)、移动应用开发、游戏开发等领域。
JavaScript的历史:
-
1995年:由Brendan Eich在Netscape公司开发,最初名为Mocha,后改为LiveScript,最终定名为JavaScript
-
1996年:微软发布JScript,与JavaScript兼容
-
1997年:ECMAScript成为JavaScript的标准化规范
-
2009年:Node.js发布,使JavaScript能够运行在服务器端
-
2015年:ECMAScript 6(ES6)发布,带来了许多重要的新特性
JavaScript与ECMAScript的关系
ECMAScript是一种脚本语言规范,由ECMA International制定。JavaScript是ECMAScript规范的一种实现。其他实现还包括JScript(微软)和ActionScript(Adobe)。
通常所说的JavaScript版本,如ES6、ES2017等,指的是ECMAScript规范的版本。
JavaScript的引入方式
JavaScript可以通过以下方式引入到HTML页面中:
-
内部脚本:使用
<script>
标签将JavaScript代码直接嵌入HTML文档中。<script> console.log("Hello, World!"); </script>
-
<script>
标签可以放在<head>
或<body>
部分。通常建议放在<body>
底部,以避免阻塞页面渲染。
-
-
外部脚本:将JavaScript代码保存在单独的
.js
文件中,然后使用<script>
标签的src
属性引入。<script src="script.js"></script>
-
优点:代码复用、便于维护、浏览器缓存
-
-
内联事件处理程序(不推荐):
<button οnclick="alert("Clicked!")">Click Me</button>
-
缺点:结构与行为未分离,难以维护
-
考点解析:
-
推荐使用外部脚本文件的方式引入JavaScript,以实现内容、样式和行为的分离。
-
<script>
标签的async
和defer
属性可以控制脚本的加载和执行方式:-
async
:异步加载脚本,加载完成后立即执行,不保证执行顺序 -
defer
:异步加载脚本,在HTML文档解析完成后、DOMContentLoaded事件触发前按顺序执行
-
JavaScript的执行环境
JavaScript代码可以在不同的环境中执行:
-
浏览器环境:
-
提供DOM(文档对象模型)和BOM(浏览器对象模型)API
-
用于操作网页内容、响应用户交互、与服务器通信等
-
-
Node.js环境:
-
基于Chrome V8引擎构建的JavaScript运行时
-
提供文件系统、网络、操作系统等API
-
用于服务器端开发、命令行工具等
-
二、JavaScript语法基础
变量与数据类型
变量声明:
-
var
:函数作用域或全局作用域,存在变量提升var name = "Alice";
-
let
:块级作用域,不存在变量提升,不能重复声明let age = 30;
-
const
:块级作用域,声明常量,必须初始化,不能重新赋值(对于对象和数组,是引用不能变,内容可以变)const PI = 3.14159;
数据类型:
JavaScript是一种动态类型语言,变量的数据类型在运行时确定。
-
基本数据类型(原始类型):
-
String
:字符串,如"Hello"
-
Number
:数字,如123
,3.14
,NaN
,Infinity
-
Boolean
:布尔值,true
或false
-
Null
:空值,表示一个空对象指针 -
Undefined
:未定义,表示变量已声明但未赋值 -
Symbol
(ES6新增):唯一的、不可变的值,用作对象属性的标识符 -
BigInt
(ES2020新增):表示任意精度的整数
-
-
引用数据类型(复杂类型):
-
Object
:对象,如{ name: "Alice", age: 30 }
-
Array
:数组,如[1, 2, 3]
-
Function
:函数,如function greet() { ... }
-
Date
:日期对象 -
RegExp
:正则表达式对象
-
类型检测:
-
typeof
:返回操作数的数据类型字符串typeof "hello"; // "string" typeof 123; // "number" typeof true; // "boolean" typeof undefined; // "undefined" typeof null; // "object" (历史遗留问题) typeof {}; // "object" typeof []; // "object" typeof function(){}; // "function" typeof Symbol(); // "symbol"
-
instanceof
:检测构造函数的prototype
属性是否出现在对象的原型链上[] instanceof Array; // true {} instanceof Object; // true new Date() instanceof Date; // true
-
Array.isArray()
:判断是否为数组Array.isArray([]); // true
运算符与表达式
-
算术运算符:
+
,-
,*
,/
,%
(取余),++
(自增),--
(自减),**
(幂,ES7) -
赋值运算符:
=
,+=
,-=
,*=
,/=
,%=
,**=
-
比较运算符:
==
(相等,会进行类型转换),!=
(不等),===
(严格相等,不进行类型转换),!==
(严格不等),>
,<
,>=
,<=
-
逻辑运算符:
&&
(逻辑与),||
(逻辑或),!
(逻辑非)-
短路求值:
-
expr1 && expr2
:如果expr1
为假,则不计算expr2
-
expr1 || expr2
:如果expr1
为真,则不计算expr2
-
-
-
位运算符:
&
(按位与),|
(按位或),^
(按位异或),~
(按位非),<<
(左移),>>
(有符号右移),>>>
(无符号右移) -
条件(三元)运算符:
condition ? exprIfTrue : exprIfFalse
let result = (age >= 18) ? "Adult" : "Minor";
-
逗号运算符:从左到右计算表达式,并返回最后一个表达式的值
let x = (1, 2, 3); // x = 3
-
其他运算符:
typeof
,instanceof
,new
,delete
,in
,void
控制流程
-
条件语句:
-
if...else if...else
:if (score >= 90) { grade = "A"; } else if (score >= 80) { grade = "B"; } else { grade = "C"; }
-
switch
:switch (day) { case 0: console.log("Sunday"); break; case 1: console.log("Monday"); break; default: console.log("Invalid day"); }
-
-
循环语句:
-
for
:for (let i = 0; i < 5; i++) { console.log(i); }
-
while
:let i = 0; while (i < 5) { console.log(i); i++; }
-
do...while
:let i = 0; do { console.log(i); i++; } while (i < 5);
-
for...in
:遍历对象的可枚举属性(包括原型链上的)const person = { name: "Alice", age: 30 }; for (let key in person) { console.log(key + ": " + person[key]); }
-
for...of
(ES6新增):遍历可迭代对象(如Array, String, Map, Set)的值const colors = ["red", "green", "blue"]; for (let color of colors) { console.log(color); }
-
-
跳转语句:
-
break
:跳出循环或switch
语句 -
continue
:跳过当前循环的剩余部分,进入下一次迭代 -
return
:从函数中返回值并退出函数 -
throw
:抛出异常
-
函数定义与调用
函数是可重用的代码块,用于执行特定任务。
函数定义:
-
函数声明:
function greet(name) { return "Hello, " + name + "!"; }
-
函数声明会被提升
-
-
函数表达式:
const greet = function(name) { return "Hello, " + name + "!"; };
-
函数表达式不会被提升
-
-
箭头函数(ES6新增):
const greet = (name) => { return "Hello, " + name + "!"; }; // 简写形式 const add = (a, b) => a + b;
-
箭头函数没有自己的
this
、arguments
、super
或new.target
-
this
值由外层作用域决定 -
不能用作构造函数
-
函数调用:
let message = greet("Alice"); // 调用函数并传入参数 console.log(message); // "Hello, Alice!"
函数参数:
-
默认参数(ES6新增):
function greet(name = "Guest") { return "Hello, " + name + "!"; } greet(); // "Hello, Guest!"
-
剩余参数(ES6新增):将多余的参数收集到一个数组中
function sum(...numbers) { return numbers.reduce((acc, curr) => acc + curr, 0); } sum(1, 2, 3, 4); // 10
-
arguments对象:函数内部可访问的类数组对象,包含所有传入的参数(箭头函数中不可用)
function logArgs() { for (let i = 0; i < arguments.length; i++) { console.log(arguments[i]); } }
作用域与闭包
作用域(Scope):变量和函数的可访问范围。
-
全局作用域:在代码任何地方都可以访问
-
函数作用域:变量在函数内部定义,只能在函数内部访问(
var
声明) -
块级作用域(ES6新增):变量在代码块(
{}
)内部定义,只能在块内部访问(let
和const
声明)
词法作用域(静态作用域):JavaScript采用词法作用域,函数的作用域在函数定义时确定,而不是在函数调用时确定。
变量提升(Hoisting):var
声明的变量和函数声