JavaScript基本语法与结构解析
JavaScript 变量
在 JavaScript 中,变量是用于存储数据值的容器。变量的声明和使用是编程的基础操作之一。
变量声明
JavaScript 有几种声明变量的方式,其中最常见的是使用 var
、let
和 const
关键字。
var
关键字:这是 JavaScript 早期用于声明变量的关键字。它具有函数作用域,而不是块级作用域。
function exampleVar() {
if (true) {
var localVar = 'I am a var variable';
console.log(localVar);
}
console.log(localVar);
}
exampleVar();
在上述代码中,localVar
虽然在 if
块内声明,但由于 var
的函数作用域特性,在 if
块外部依然可以访问到它。
let
关键字:let
是 ES6 引入的声明变量的关键字,它具有块级作用域。
function exampleLet() {
if (true) {
let localVar = 'I am a let variable';
console.log(localVar);
}
// console.log(localVar); // 这行代码会报错,因为 localVar 在此处不可访问
}
exampleLet();
这里 localVar
在 if
块外部无法访问,因为 let
定义的变量只在其所在的块级作用域内有效。
const
关键字:const
同样是 ES6 引入的,用于声明常量。常量一旦声明,其值就不能再改变,并且也具有块级作用域。
function exampleConst() {
const PI = 3.14159;
// PI = 3.14; // 这行代码会报错,因为 PI 是常量,不能重新赋值
console.log(PI);
}
exampleConst();
变量命名规则
- 只能包含字母、数字、下划线(
_
)和美元符号($
):例如myVariable
、_underscore
、$dollar
都是合法的变量名,但1stVariable
是不合法的,因为变量名不能以数字开头。 - 不能是 JavaScript 关键字或保留字:像
if
、else
、function
等关键字不能作为变量名。保留字如await
(在非async
函数中)也不能用作变量名。 - 区分大小写:
myVar
和MyVar
是两个不同的变量。
数据类型
JavaScript 拥有丰富的数据类型,可分为原始数据类型和引用数据类型。
原始数据类型
- 数值(Number):JavaScript 中的数值类型既可以表示整数,也可以表示浮点数。
let integer = 42;
let floatingPoint = 3.14;
let anotherNumber = Number('42'); // 将字符串转换为数值
console.log(typeof integer); // 输出 "number"
JavaScript 还提供了一些特殊的数值,如 NaN
(表示非数字)、Infinity
(表示无穷大)和 -Infinity
(表示负无穷大)。
let notANumber = NaN;
let positiveInfinity = Infinity;
let negativeInfinity = -Infinity;
console.log(isNaN(notANumber)); // 输出 true
console.log(positiveInfinity > 1000000); // 输出 true
- 字符串(String):用于表示文本数据。字符串可以用单引号(
'
)、双引号("
)或模板字面量(
let singleQuoted = 'This is a single - quoted string';
let doubleQuoted = "This is a double - quoted string";
let templateLiteral = `This is a template literal. The value of 2 + 2 is ${2 + 2}`;
console.log(templateLiteral); // 输出 "This is a template literal. The value of 2 + 2 is 4"
字符串提供了许多有用的方法,如 length
属性获取字符串长度,charAt()
方法获取指定位置的字符等。
let str = 'Hello, World!';
console.log(str.length); // 输出 13
console.log(str.charAt(0)); // 输出 'H'
- 布尔值(Boolean):只有两个值,
true
和false
,常用于逻辑判断。
let isDone = true;
let isError = false;
if (isDone) {
console.log('Task completed');
}
- 空值(null):表示一个空的对象引用。
let myNull = null;
console.log(typeof myNull); // 输出 "object"(这是 JavaScript 的历史遗留问题)
- 未定义(undefined):当一个变量声明但未赋值时,其值为
undefined
。
let myVar;
console.log(myVar); // 输出 undefined
- 符号(Symbol):ES6 引入的一种新的原始数据类型,符号的值是唯一的。
let sym1 = Symbol('description');
let sym2 = Symbol('description');
console.log(sym1 === sym2); // 输出 false
引用数据类型
- 对象(Object):对象是一种复杂的数据结构,用于存储多个键值对。
let person = {
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
};
console.log(person.name); // 输出 'John'
console.log(person.address.city); // 输出 'New York'
可以使用 Object.keys()
方法获取对象的所有键,使用 Object.values()
方法获取对象的所有值。
let keys = Object.keys(person);
let values = Object.values(person);
console.log(keys); // 输出 ['name', 'age', 'address']
console.log(values); // 输出 ['John', 30, {city: 'New York', country: 'USA'}]
- 数组(Array):数组是一种特殊的对象,用于存储有序的数据集合。
let numbers = [1, 2, 3, 4, 5];
console.log(numbers.length); // 输出 5
console.log(numbers[0]); // 输出 1
数组提供了许多方法,如 push()
在数组末尾添加元素,pop()
删除数组末尾的元素等。
numbers.push(6);
console.log(numbers); // 输出 [1, 2, 3, 4, 5, 6]
numbers.pop();
console.log(numbers); // 输出 [1, 2, 3, 4, 5]
- 函数(Function):在 JavaScript 中,函数也是一种对象。函数可以接受参数并返回值。
function add(a, b) {
return a + b;
}
let result = add(3, 5);
console.log(result); // 输出 8
运算符
JavaScript 提供了丰富的运算符,用于执行各种操作。
算术运算符
- 加法(
+
):用于两个数值相加,当其中一个操作数是字符串时,会进行字符串拼接。
let num1 = 5;
let num2 = 3;
let sum = num1 + num2;
console.log(sum); // 输出 8
let str1 = 'Hello';
let str2 = 'World';
let combinedStr = str1 + ', ' + str2;
console.log(combinedStr); // 输出 'Hello, World'
- 减法(
-
)、乘法(*
)、除法(/
)和取模(%
):这些运算符分别用于减法、乘法、除法和取模运算。
let subResult = num1 - num2;
let mulResult = num1 * num2;
let divResult = num1 / num2;
let modResult = num1 % num2;
console.log(subResult); // 输出 2
console.log(mulResult); // 输出 15
console.log(divResult); // 输出 1.6666666666666667
console.log(modResult); // 输出 2
赋值运算符
- 简单赋值(
=
):将右侧的值赋给左侧的变量。
let x = 10;
- 复合赋值运算符:如
+=
、-=
、*=
、/=
、%=
等,先进行相应的算术运算,再进行赋值。
let y = 5;
y += 3; // 相当于 y = y + 3
console.log(y); // 输出 8
比较运算符
- 相等(
==
)和严格相等(===
):==
会在比较前进行类型转换,而===
不会。
console.log(5 == '5'); // 输出 true,因为会进行类型转换
console.log(5 === '5'); // 输出 false,类型不同
- 不相等(
!=
)和严格不相等(!==
):与相等运算符相反。
console.log(5 != '5'); // 输出 false
console.log(5!== '5'); // 输出 true
- 大于(
>
)、小于(<
)、大于等于(>=
)和小于等于(<=
):用于比较数值大小。
console.log(5 > 3); // 输出 true
console.log(5 < 3); // 输出 false
逻辑运算符
- 逻辑与(
&&
):只有当两个操作数都为true
时,结果才为true
。
let a = true;
let b = false;
console.log(a && b); // 输出 false
- 逻辑或(
||
):只要两个操作数中有一个为true
,结果就为true
。
console.log(a || b); // 输出 true
- 逻辑非(
!
):用于取反操作,将true
变为false
,false
变为true
。
console.log(!a); // 输出 false
位运算符
- 按位与(
&
):对两个操作数的每一位进行与运算,只有当两位都为1
时,结果位才为1
。
let num3 = 5; // 二进制 0101
let num4 = 3; // 二进制 0011
let bitwiseAnd = num3 & num4; // 二进制 0001,结果为 1
console.log(bitwiseAnd);
- 按位或(
|
):对两个操作数的每一位进行或运算,只要有一位为1
,结果位就为1
。
let bitwiseOr = num3 | num4; // 二进制 0111,结果为 7
console.log(bitwiseOr);
- 按位异或(
^
):对两个操作数的每一位进行异或运算,当两位不同时,结果位为1
。
let bitwiseXor = num3 ^ num4; // 二进制 0110,结果为 6
console.log(bitwiseXor);
- 按位非(
~
):对操作数的每一位进行取反操作。
let bitwiseNot = ~num3; // 二进制 1010,结果为 -6
console.log(bitwiseNot);
流程控制语句
流程控制语句用于控制程序的执行顺序。
if...else
语句
用于根据条件执行不同的代码块。
let age = 18;
if (age >= 18) {
console.log('You are an adult');
} else {
console.log('You are a minor');
}
switch...case
语句
用于基于不同的条件执行不同的代码块,它比多个 if...else
语句更简洁。
let day = 'Monday';
switch (day) {
case 'Monday':
console.log('It is the start of the week');
break;
case 'Tuesday':
console.log('The week is in progress');
break;
default:
console.log('Another day of the week');
}
for
循环
用于重复执行一段代码指定的次数。
for (let i = 0; i < 5; i++) {
console.log(i);
}
while
循环
只要指定的条件为 true
,就会重复执行代码块。
let count = 0;
while (count < 3) {
console.log(count);
count++;
}
do...while
循环
与 while
循环类似,但它会先执行一次代码块,然后再检查条件。
let num = 0;
do {
console.log(num);
num++;
} while (num < 3);
函数
函数是 JavaScript 中封装可重用代码的一种方式。
函数定义
- 函数声明:使用
function
关键字定义函数。
function greet(name) {
return 'Hello, ' + name;
}
let greeting = greet('John');
console.log(greeting); // 输出 'Hello, John'
- 函数表达式:将函数赋值给一个变量。
let addNumbers = function (a, b) {
return a + b;
};
let sumResult = addNumbers(2, 3);
console.log(sumResult); // 输出 5
- 箭头函数:ES6 引入的一种更简洁的函数定义方式。
let multiply = (a, b) => a * b;
let product = multiply(4, 5);
console.log(product); // 输出 20
函数参数和返回值
- 参数:函数可以接受零个或多个参数,这些参数在函数调用时传递。
function calculateArea(radius) {
return Math.PI * radius * radius;
}
let area = calculateArea(5);
console.log(area); // 输出约 78.53981633974483
- 返回值:函数可以通过
return
关键字返回一个值。如果没有return
语句,函数默认返回undefined
。
function sayHello() {
console.log('Hello');
// 这里没有 return 语句,所以默认返回 undefined
}
let result = sayHello();
console.log(result); // 输出 undefined
函数作用域和闭包
- 函数作用域:变量的作用域是其可访问的范围。函数作用域意味着变量在函数内部定义,在函数外部无法访问。
function innerFunction() {
let localVar = 'I am only accessible inside this function';
console.log(localVar);
}
// console.log(localVar); // 这行代码会报错,因为 localVar 在此处不可访问
innerFunction();
- 闭包:闭包是指函数可以访问其外部函数作用域中的变量,即使外部函数已经执行完毕。
function outerFunction() {
let outerVar = 'I am from outer function';
function innerFunction() {
console.log(outerVar);
}
return innerFunction;
}
let closure = outerFunction();
closure(); // 输出 'I am from outer function'
对象
对象是 JavaScript 中重要的数据结构,用于组织和存储相关的数据和功能。
对象字面量
使用对象字面量可以快速创建对象。
let car = {
brand: 'Toyota',
model: 'Corolla',
year: 2020,
startEngine: function () {
console.log('The engine has started');
}
};
console.log(car.brand); // 输出 'Toyota'
car.startEngine(); // 输出 'The engine has started'
访问对象属性
- 点表示法:使用点(
.
)来访问对象的属性。
console.log(car.model); // 输出 'Corolla'
- 方括号表示法:使用方括号(
[]
)可以通过变量来访问对象属性,并且可以访问属性名包含特殊字符的属性。
let property = 'year';
console.log(car[property]); // 输出 2020
let specialProperty = 'engine type';
let specialCar = {
'engine type': 'Gasoline'
};
console.log(specialCar[specialProperty]); // 输出 'Gasoline'
对象方法
对象方法是对象中定义的函数。
let personObject = {
name: 'Alice',
sayHello: function () {
console.log('Hello, my name is'+ this.name);
}
};
personObject.sayHello(); // 输出 'Hello, my name is Alice'
这里的 this
关键字指向调用该方法的对象。
原型和原型链
- 原型:每个 JavaScript 对象都有一个原型对象。原型对象可以包含属性和方法,这些属性和方法可以被对象继承。
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(this.name +'makes a sound');
};
let dog = new Animal('Buddy');
dog.speak(); // 输出 'Buddy makes a sound'
- 原型链:当访问一个对象的属性或方法时,如果对象本身没有该属性或方法,JavaScript 会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的顶端(
null
)。
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {
console.log(this.name +'barks');
};
let myDog = new Dog('Max');
myDog.bark(); // 输出 'Max barks'
myDog.speak(); // 输出 'Max makes a sound'
数组
数组是用于存储多个值的有序集合。
数组创建
- 数组字面量:使用方括号(
[]
)创建数组。
let numbersArray = [1, 2, 3, 4, 5];
new Array()
构造函数:也可以使用new Array()
构造函数创建数组。
let newNumbersArray = new Array(1, 2, 3);
数组操作
- 访问数组元素:通过索引访问数组元素,索引从
0
开始。
console.log(numbersArray[0]); // 输出 1
- 修改数组元素:可以通过索引修改数组元素的值。
numbersArray[2] = 30;
console.log(numbersArray); // 输出 [1, 2, 30, 4, 5]
- 添加和删除元素:
push()
:在数组末尾添加一个或多个元素。
numbersArray.push(6);
console.log(numbersArray); // 输出 [1, 2, 30, 4, 5, 6]
- **`pop()`**:删除数组末尾的元素并返回该元素。
let poppedElement = numbersArray.pop();
console.log(poppedElement); // 输出 6
console.log(numbersArray); // 输出 [1, 2, 30, 4, 5]
- **`unshift()`**:在数组开头添加一个或多个元素。
numbersArray.unshift(0);
console.log(numbersArray); // 输出 [0, 1, 2, 30, 4, 5]
- **`shift()`**:删除数组开头的元素并返回该元素。
let shiftedElement = numbersArray.shift();
console.log(shiftedElement); // 输出 0
console.log(numbersArray); // 输出 [1, 2, 30, 4, 5]
数组遍历
for
循环:
for (let i = 0; i < numbersArray.length; i++) {
console.log(numbersArray[i]);
}
forEach()
方法:
numbersArray.forEach(function (element) {
console.log(element);
});
map()
方法:用于创建一个新数组,其元素是原数组元素调用一个函数后的返回值。
let squaredNumbers = numbersArray.map(function (num) {
return num * num;
});
console.log(squaredNumbers); // 输出 [1, 4, 900, 16, 25]
filter()
方法:用于创建一个新数组,其元素是原数组中满足指定条件的元素。
let evenNumbers = numbersArray.filter(function (num) {
return num % 2 === 0;
});
console.log(evenNumbers); // 输出 [2, 4]
模块
在 JavaScript 中,模块是一种将代码组织成独立单元的方式,有助于提高代码的可维护性和复用性。
ES6 模块
ES6 引入了原生的模块系统。一个模块可以导出变量、函数、类等,其他模块可以导入这些导出的内容。
- 导出:使用
export
关键字导出内容。
// math.js
export function add(a, b) {
return a + b;
}
export const PI = 3.14159;
- 导入:使用
import
关键字导入模块中的内容。
// main.js
import {add, PI} from './math.js';
let sum = add(2, 3);
console.log(sum); // 输出 5
console.log(PI); // 输出 3.14159
其他模块系统
- CommonJS 模块:常用于 Node.js 环境。使用
exports
或module.exports
导出,使用require()
导入。
// math.js (CommonJS)
function add(a, b) {
return a + b;
}
exports.add = add;
// main.js (CommonJS)
let math = require('./math.js');
let sumResult = math.add(2, 3);
console.log(sumResult); // 输出 5
- AMD(Asynchronous Module Definition):主要用于浏览器环境,通过
define()
定义模块,require()
加载模块。
// math.js (AMD)
define(function () {
function add(a, b) {
return a + b;
}
return {
add: add
};
});
// main.js (AMD)
require(['./math.js'], function (math) {
let sum = math.add(2, 3);
console.log(sum); // 输出 5
});
事件处理
在 JavaScript 中,事件处理用于响应用户的操作,如点击按钮、滚动页面等。
HTML 事件处理
可以在 HTML 标签中直接添加事件处理属性。
<button onclick="alert('Button clicked')">Click me</button>
DOM 事件处理
- 通过
addEventListener()
方法:这是一种更灵活的事件处理方式。
<button id="myButton">Click me</button>
<script>
let button = document.getElementById('myButton');
button.addEventListener('click', function () {
console.log('Button clicked');
});
</script>
- 事件对象:在事件处理函数中,可以访问事件对象,它包含了与事件相关的信息。
<input type="text" id="myInput">
<script>
let input = document.getElementById('myInput');
input.addEventListener('input', function (event) {
console.log('Input value:'+ event.target.value);
});
</script>
错误处理
在 JavaScript 中,错误处理是确保程序稳健运行的重要部分。
try...catch...finally
语句
用于捕获和处理异常。
try {
let result = 10 / 0; // 这会导致一个除零错误
console.log(result);
} catch (error) {
console.log('An error occurred:'+ error.message);
} finally {
console.log('This will always be printed');
}
自定义错误
可以通过继承 Error
类来创建自定义错误。
class MyCustomError extends Error {
constructor(message) {
super(message);
this.name = 'MyCustomError';
}
}
try {
throw new MyCustomError('This is a custom error');
} catch (error) {
if (error instanceof MyCustomError) {
console.log('Caught custom error:'+ error.message);
} else {
console.log('Caught other error:'+ error.message);
}
}
通过对上述 JavaScript 基本语法与结构的深入理解,开发者可以更好地利用这门语言进行各种应用程序的开发,无论是前端的网页交互,还是后端的服务器端编程。同时,随着不断的实践和学习,对 JavaScript 的掌握也会更加熟练和深入。