10.1 JavaScript的概述
JavaScript 是一种广泛使用的高级编程语言,最初由 Netscape 公司的 Brendan Eich 在 1995 年创建。它是一种主要在 Web 浏览器中执行的脚本语言,但也可以用于服务器端开发(如 Node.js)和其他应用程序。
主要特点
- 解释型:JavaScript 代码通常不需要编译,可以直接由浏览器或其他环境中的解释器执行。
- 基于原型:JavaScript 使用基于原型的对象模型,与传统的类继承不同。
- 弱类型:变量的数据类型是在运行时确定的,开发者不需要提前声明变量的类型。
- 动态:可以在运行时修改对象和函数。
- 事件驱动:非常适合处理用户交互和异步操作。
- 跨平台:几乎所有的现代 Web 浏览器都支持 JavaScript,且有多种运行环境(如 Node.js)可以运行 JavaScript。
应用场景
- Web 开发:最普遍的应用是前端开发,用来增加网页的交互性,比如表单验证、动态内容加载等。
- 后端开发:通过 Node.js,JavaScript 可以用于构建服务器端应用。
- 移动应用开发:使用框架如 React Native 或 Ionic 可以用 JavaScript 开发跨平台的移动应用。
- 游戏开发:结合 HTML5 和 Canvas,可以开发简单的网页游戏。
- 桌面应用开发:使用 Electron 等框架,可以用 JavaScript 构建跨平台的桌面应用程序。
- 物联网 (IoT):JavaScript 也可以用于开发 IoT 设备上的应用。
历史发展
- 1995年:JavaScript 最初被命名为 Mocha,后来改为 LiveScript,最终定名为 JavaScript。
- 1996年:Netscape 将 JavaScript 提交给 ECMA 国际进行标准化,最终产生了 ECMAScript 标准。
- 1997年:第一个版本的 ECMAScript 发布。
- 2009年:随着 Node.js 的发布,JavaScript 成为了服务器端开发的语言之一。
- 2015年:ECMAScript 6(ES6)发布,引入了许多新特性,如箭头函数、模板字符串、解构赋值等,极大地增强了语言的功能性和易用性。
学习资源
对于初学者来说,有许多免费和付费的在线课程、书籍和文档可以帮助学习 JavaScript,包括 MDN Web 文档、W3Schools、freeCodeCamp 等网站提供的教程和练习。
入门案例 - Hello, World!
为了帮助初学者更好地理解 JavaScript 的基本概念和用法,下面是一个简单的 "Hello, World!" 示例。这个例子展示了如何将 JavaScript 代码嵌入到 HTML 页面中,并通过 DOM 操作改变页面内容。
HTML 文件结构
首先,我们需要一个基本的 HTML 文件结构,这将作为承载 JavaScript 代码的容器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我的第一个 JavaScript 程序</title>
</head>
<body>
<h1>欢迎来到 JavaScript 世界!</h1>
<p id="greeting"></p>
<!-- JavaScript 代码可以放在 body 的末尾 -->
<script>
// 这里是 JavaScript 代码
document.getElementById('greeting').innerText = 'Hello, World!';
</script>
</body>
</html>
JavaScript 代码解析
document.getElementById('greeting')
: 这是一个 DOM 方法,用于获取页面中 ID 为greeting
的元素。.innerText = 'Hello, World!';
: 这行代码将找到的元素的文本内容设置为 "Hello, World!"。
放置位置的重要性
- 头部 (
<head>
): 如果将<script>
放在<head>
中,可能会导致页面渲染延迟,因为浏览器会暂停解析 HTML 直到脚本执行完毕。 - 底部 (
<body>
): 将<script>
放在<body>
的底部可以确保页面的主要内容先加载,提高用户体验,特别是在脚本文件较大或执行时间较长时更为重要。
总结
通过这个简单的 "Hello, World!" 案例,你可以看到 JavaScript 如何与 HTML 协同工作,以及如何使用基本的 DOM 操作来改变页面内容。这对于刚开始学习 JavaScript 的人来说是一个很好的起点。此外,了解 <script>
标签的最佳放置位置有助于优化网页性能,提供更好的用户体验。希望这个案例能帮助你更好地理解和掌握 JavaScript 的基础知识。
10.2 JavaScript语法
1. 注释
// 这是一个单行注释
/* 这是一个
多行注释 */
2. 标识符
let _name = "Kimi"; // 有效的标识符
let $age = 30; // 有效的标识符
let name = "Kimi"; // 有效的标识符
3. 数据类型
let number = 10; // Number
let text = "Hello"; // String
let isTrue = true; // Boolean
let undefinedVar; // Undefined
let nullVar = null; // Null
let symbol = Symbol("mySymbol"); // Symbol
let bigNumber = 1234567890123456789012345678901234567890n; // BigInt
4. 变量声明
let newVariable = "This is a new variable"; // 使用 let 声明变量
const constantVariable = "This is a constant variable"; // 使用 const 声明常量
var oldStyleVariable = "This is an old-style variable"; // 使用 var 声明变量
5. 操作符
let a = 5;
let b = 3;
console.log(a + b); // 算术操作符
console.log(a - b);
console.log(a * b);
console.log(a / b);
console.log(a % b);
a++; // 递增操作符
console.log(a);
6. 控制流
let score = 85;
if (score > 80) {
console.log("优秀");
} else if (score > 70) {
console.log("良好");
} else {
console.log("及格");
}
for (let i = 0; i < 5; i++) {
console.log("循环 " + i);
}
while (i < 3) {
console.log("循环 " + i);
i++;
}
7. 函数
function sayHello() {
console.log("Hello");
}
sayHello();
const sayHelloArrow = () => {
console.log("Hello with arrow function");
};
sayHelloArrow();
8. 数组和对象
let fruits = ["Apple", "Banana", "Cherry"];
console.log(fruits[1]); // "Banana"
let person = {
name: "Kimi",
age: 30,
greet: function() {
console.log("Hello, " + this.name);
}
};
person.greet(); // "Hello, Kimi"
9. 解构赋值
let [first, second] = [1, 2];
console.log(first); // 1
console.log(second); // 2
let { name, age } = { name: "Kimi", age: 30 };
console.log(name); // "Kimi"
console.log(age); // 30
10. 模板字符串
let name = "Kimi";
let greeting = `Hello, ${name}!`;
console.log(greeting); // "Hello, Kimi!"
11. 类和模块
案例(类):
javascript
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log("Hello, " + this.name);
}
}
let person = new Person("Kimi");
person.sayHello(); // "Hello, Kimi"
案例(模块):
javascript
// mathUtils.js
export function add(x, y) {
return x + y;
}
// app.js
import { add } from './mathUtils.js';
console.log(add(5, 3)); // 输出 8
12. 错误处理
案例:
javascript
try {
throw new Error("Something went wrong!");
} catch (e) {
console.log(e.message); // "Something went wrong!"
} finally {
console.log("The end.");
}
13. 异步编程
案例(Promise):
javascript
function asyncOperation() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("操作完成!");
}, 2000);
});
}
asyncOperation().then(result => {
console.log(result); // 输出 "操作完成!"
});
案例(async/await):
javascript
async function asyncCall() {
try {
const result = await asyncOperation();
console.log(result); // 输出 "操作完成!"
} catch (error) {
console.error("Error:", error);
}
}
asyncCall();
14. JSON
案例:
javascript
let obj = { name: "Kimi", age: 30 };
let jsonString = JSON.stringify(obj);
console.log(jsonString); // '{"name":"Kimi","age":30}'
let parsedObj = JSON.parse(jsonString);
console.log(parsedObj.name); // "Kimi"
15. 作用域和闭包
作用域指的是变量和函数的可见性。在 JavaScript 中,有全局作用域、函数作用域和块级作用域(由 let
和 const
创建)。
闭包是 JavaScript 中一个强大的特性,它允许函数访问并操作函数外部的变量。
案例:
javascript
function createGreeting() {
let name = "Kimi";
return function() {
console.log("Hello, " + name + "!");
};
}
const greet = createGreeting();
greet(); // 输出 "Hello, Kimi!"
16. 原型和原型链
JavaScript 中的对象是基于原型的,每个对象都有一个原型对象,通过 __proto__
属性可以访问。
案例:
javascript
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name);
};
const person = new Person("Kimi");
person.sayHello(); // 输出 "Hello, I'm Kimi"
17. 正则表达式
JavaScript 内置了对正则表达式的支持,用于字符串的匹配、搜索、替换等操作。
案例:
javascript
let regex = /hello/;
let str = "hello world";
console.log(regex.test(str)); // 输出 true
let replaced = str.replace("hello", "hi");
console.log(replaced); // 输出 "hi world"
18. 事件处理
JavaScript 可以为 HTML 元素添加事件监听器,响应用户的交互行为。
案例:
html
<button id="clickMe">点击我</button>
<script>
document.getElementById("clickMe").addEventListener("click", function() {
alert("按钮被点击了!");
});
</script>
19. 异步编程进阶
JavaScript 提供了多种异步编程的方法,包括 Promise、async/await。
案例(使用 Promise):
javascript
function asyncOperation() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("操作完成!");
}, 2000);
});
}
asyncOperation().then(result => {
console.log(result); // 输出 "操作完成!"
});
案例(使用 async/await):
javascript
async function asyncCall() {
const result = await asyncOperation();
console.log(result); // 输出 "操作完成!"
}
asyncCall();
20. 模块化
JavaScript 支持模块化编程,允许将代码分割成独立的模块。
案例(使用 ES6 模块):
javascript
// mathUtils.js
export function add(x, y) {
return x + y;
}
export function subtract(x, y) {
return x - y;
}
// app.js
import { add, subtract } from './mathUtils.js';
console.log(add(5, 3)); // 输出 8
console.log(subtract(5, 3)); // 输出 2
这些案例展示了 JavaScript 的一些核心概念和实际应用。通过这些案例,你可以更好地理解 JavaScript 的语法和用法,并将其应用到实际的项目中。
综合案例
以下是一个综合案例,它包含了 HTML 和内嵌的 JavaScript。这个例子将展示一个简单的网页,其中包含一个表单,用户可以输入名字,点击按钮后会显示一条个性化的欢迎信息
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>综合案例</title>
<script>
// 这个函数会在页面加载时执行
function initPage() {
// 将欢迎信息设置为默认值
document.getElementById("welcomeMessage").textContent = "请输入您的名字,然后点击按钮。";
}
// 这个函数会在按钮点击时执行
function greetUser() {
// 获取用户输入的名字
let name = document.getElementById("userName").value;
// 检查名字是否为空
if (name.trim() === "") {
// 如果名字为空,显示提示信息
document.getElementById("welcomeMessage").textContent = "名字不能为空,请重新输入。";
} else {
// 如果名字不为空,显示欢迎信息
document.getElementById("welcomeMessage").textContent = "你好," + name + "!欢迎来到我们的网站。";
}
}
</script>
</head>
<body onload="initPage()">
<h1>欢迎到访</h1>
<p id="welcomeMessage">请输入您的名字,然后点击按钮。</p>
<!-- 用户输入名字的表单 -->
<label for="userName">名字:</label>
<input type="text" id="userName" name="userName">
<!-- 按钮,点击时调用 greetUser 函数 -->
<button onclick="greetUser()">点击这里</button>
</body>
</html>
在这个综合案例中,我们使用了以下 JavaScript 概念:
- 函数定义:定义了
initPage
和greetUser
两个函数。 - 事件处理:使用
onload
事件在页面加载时执行initPage
函数,使用onclick
事件在按钮点击时执行greetUser
函数。 - DOM 操作:通过
document.getElementById
获取页面元素,并修改它们的textContent
。 - 用户输入:通过
document.getElementById("userName").value
获取用户在文本框中的输入。 - 字符串操作:使用字符串拼接来构造欢迎信息,并使用
trim
方法来去除用户输入的前后空格。
这个案例展示了如何在实际的 HTML 页面中使用 JavaScript 来处理用户交互和动态更新页面内容。
10.3 JavaScript对象
在 JavaScript 中,对象是一组键值对的集合,其中键是字符串(或者可以被转换为字符串的值),值可以是任何数据类型。对象用于表示复杂的数据结构和属性集合,它们是 JavaScript 中最强大的数据类型之一。
创建对象
-
对象字面量: 这是创建对象最常用的方法。
javascript
const person = { firstName: "Kimi", lastName: "Chat", age: 30, greet: function() { console.log("Hello, " + this.firstName + " " + this.lastName); } };
-
构造函数: 使用构造函数创建对象,可以创建具有相同属性和方法的对象。
javascript
function Person(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; this.greet = function() { console.log("Hello, " + this.firstName + " " + this.lastName); }; } const person1 = new Person("Kimi", "Chat", 30);
-
Object.create(): 使用
Object.create()
方法基于一个现有对象创建一个新对象。javascript
const personProto = { greet: function() { console.log("Hello, " + this.firstName + " " + this.lastName); } }; const person = Object.create(personProto); person.firstName = "Kimi"; person.lastName = "Chat"; person.age = 30;
-
类(ES6): 使用
class
关键字定义类,它提供了一种新的语法,使得创建对象和实现继承更加清晰。javascript
class Person { constructor(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } greet() { console.log("Hello, " + this.firstName + " " + this.lastName); } } const person = new Person("Kimi", "Chat", 30);
访问对象属性
-
点表示法:
javascript
console.log(person.firstName); // 输出 "Kimi"
-
方括号表示法:
javascript
console.log(person["firstName"]); // 输出 "Kimi" let key = "firstName"; console.log(person[key]); // 输出 "Kimi"
修改对象属性
javascript
person.firstName = "Moonshot";
console.log(person.firstName); // 输出 "Moonshot"
删除对象属性
javascript
delete person.age;
console.log(person.age); // 输出 "undefined"
枚举属性
javascript
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key + ": " + person[key]);
}
}
Object 方法
JavaScript 提供了许多内置的 Object
方法来操作对象,例如:
Object.keys(obj)
:返回一个包含对象所有自身属性(不包括原型链上的属性)的数组。Object.values(obj)
:返回一个包含对象所有自身属性值的数组。Object.entries(obj)
:返回一个包含对象所有自身属性的键值对数组。
javascript
console.log(Object.keys(person)); // 输出 ["firstName", "lastName", "greet"]
console.log(Object.values(person)); // 输出 ["Kimi", "Chat", function()]
console.log(Object.entries(person)); // 输出 [["firstName", "Kimi"], ["lastName", "Chat"], ["greet", function() {}]]
原型链
JavaScript 中的对象都具有原型,对象的属性和方法查找会沿着原型链进行。
javascript
const proto = {
sayHello() {
console.log("Hello");
}
};
const obj = Object.create(proto);
obj.sayHello(); // 输出 "Hello"
在这个例子中,obj
对象没有自己的 sayHello
方法,但是它可以通过原型链访问 proto
对象上的 sayHello
方法。
通过这些概念和方法,你可以在 JavaScript 中有效地创建、操作和使用对象。
JavaScript 对象的复杂性和功能远远超出了基本的创建和操作。以下是一些更高级的对象特性和用法:
动态属性名和方法
JavaScript 允许你动态地创建属性名和方法名。
案例:
javascript
const prefix = "user";
const person = {};
person[prefix + 'Name'] = 'Kimi';
person[prefix + 'Age'] = 30;
console.log(person.userName); // 输出 "Kimi"
console.log(person.userAge); // 输出 30
对象的复制
JavaScript 提供了几种复制对象的方法,包括浅复制和深复制。
案例(浅复制):
javascript
const original = { a: 1, b: { c: 2 } };
const copied = { ...original };
original.a = 3;
copied.b.c = 4;
console.log(original); // { a: 3, b: { c: 2 } }
console.log(copied); // { a: 1, b: { c: 4 } }
案例(深复制):
javascript
const original = { a: 1, b: { c: 2 } };
const copied = JSON.parse(JSON.stringify(original));
original.a = 3;
original.b.c = 4;
console.log(original); // { a: 3, b: { c: 4 } }
console.log(copied); // { a: 1, b: { c: 2 } }
对象的迭代
ES6 引入了新的迭代器协议,允许对象被迭代。
案例:
javascript
const person = {
[Symbol.iterator]: function* () {
yield this.firstName;
yield this.lastName;
},
firstName: "Kimi",
lastName: "Chat"
};
for (const value of person) {
console.log(value); // "Kimi" 和 "Chat"
}
Proxy 和 Reflect
Proxy
对象用于创建一个对象的代理,从而在访问对象的属性或方法时进行拦截和自定义操作。
案例:
javascript
const person = {
_name: "Kimi",
get name() {
return this._name;
},
set name(value) {
this._name = value;
}
};
const proxyPerson = new Proxy(person, {
get(target, property, receiver) {
if (property === 'name') {
return `Mr. ${Reflect.get(target, property, receiver)}`;
}
return Reflect.get(target, property, receiver);
}
});
console.log(proxyPerson.name); // 输出 "Mr. Kimi"
proxyPerson.name = "Moonshot";
console.log(proxyPerson.name); // 输出 "Mr. Moonshot"
Object.is()
Object.is()
方法用来比较两个值是否相同,它比 ===
更严格,因为它会考虑 NaN
和 -0
的特殊性。
案例:
javascript
console.log(Object.is(0, -0)); // 输出 false
console.log(Object.is(NaN, NaN)); // 输出 true
Object.assign()
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。
案例:
javascript
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
const result = Object.assign(target, source1, source2);
console.log(result); // { a: 1, b: 2, c: 3 }
对象的序列化和反序列化
除了 JSON.stringify()
和 JSON.parse()
,JavaScript 还提供了其他序列化和反序列化的方法,如 structuredClone()
。
案例:
javascript复制
const obj = { a: 1, b: new Map([['key', 'value']]) };
const clone = structuredClone(obj);
clone.a = 2;
clone.b.set('newKey', 'newValue');
console.log(obj); // { a: 1, b: Map { 'key' => 'value' } }
console.log(clone); // { a: 2, b: Map { 'key' => 'value', 'newKey' => 'newValue' } }
这些高级特性和用法展示了 JavaScript 对象的灵活性和强大功能,使得它们在处理复杂的数据结构和实现高级编程模式时非常有用。
JavaScript 对象还有更多的高级特性和用法,这些可以帮助你更深入地理解和使用 JavaScript 对象。以下是一些额外的概念和案例:
1. Object.freeze()
和 Object.seal()
这些方法可以用来限制对象的修改。
Object.freeze(obj)
:冻结一个对象,使其成为不可变的。Object.seal(obj)
:密封一个对象,使其属性不能被添加或删除。
案例:
javascript
const obj = { a: 1 };
Object.freeze(obj);
obj.a = 2; // 无效,obj.a 仍然是 1
const sealedObj = { a: 1, b: 2 };
Object.seal(sealedObj);
sealedObj.c = 3; // 无效,属性 c 不会被添加
delete sealedObj.a; // 无效,属性 a 不会被删除
2. Object.getOwnPropertyDescriptor()
这个方法可以用来获取对象属性的描述符。
案例:
javascript
const obj = {
get value() {
return 1;
}
};
const descriptor = Object.getOwnPropertyDescriptor(obj, 'value');
console.log(descriptor.enumerable); // 输出 false
console.log(descriptor.get); // 输出 getter 函数
3. Object.setPrototypeOf()
这个方法可以用来设置对象的原型。
案例:
javascript
const proto = { method() { console.log('method'); } };
const obj = Object.create(proto);
Object.setPrototypeOf(obj, {
ownMethod() { console.log('own method'); }
});
obj.method(); // 输出 'method'
obj.ownMethod(); // 输出 'own method'
4. Object.hasOwn()
这个方法用来检查对象是否具有指定的自有属性。
案例:
javascript
const obj = { a: 1 };
console.log(Object.hasOwn(obj, 'a')); // 输出 true
console.log(Object.hasOwn(obj, 'b')); // 输出 false
5. JSON.stringify()
的高级用法
JSON.stringify()
方法不仅可以序列化对象,还可以接受替换器参数来自定义序列化过程。
案例:
javascript
const obj = { a: 1, b: 2, c: 3 };
JSON.stringify(obj, (key, value) => {
if (typeof value === 'number') {
return value * 2;
}
return value;
});
// 输出 '{"a":2,"b":4,"c":6}'
6. Date
对象和时间操作
JavaScript 的 Date
对象提供了丰富的方法来处理日期和时间。
案例:
javascript
const now = new Date();
console.log(now.getFullYear()); // 输出当前年份
console.log(now.getMonth()); // 输出当前月份(0-11)
console.log(now.getDate()); // 输出当前日期
console.log(now.getTime()); // 输出当前时间的时间戳
7. Math
对象和数值操作
Math
对象提供了一系列的数值操作函数。
案例:
javascript
console.log(Math.PI); // 输出圆周率
console.log(Math.sqrt(16)); // 输出 4
console.log(Math.pow(2, 3)); // 输出 8
console.log(Math.random()); // 输出 0 到 1 之间的随机数
8. Array
对象和数组方法
虽然 Array
是特殊的对象,但它提供了许多用于操作数组的方法。
案例:
javascript
const arr = [1, 2, 3, 4, 5];
console.log(arr.map(x => x * 2)); // 输出 [2, 4, 6, 8, 10]
console.log(arr.filter(x => x > 2)); // 输出 [3, 4, 5]
console.log(arr.reduce((acc, x) => acc + x, 0)); // 输出 15
这些高级特性和用法进一步展示了 JavaScript 对象的灵活性和强大功能,使得它们在处理复杂的数据结构和实现高级编程模式时非常有用。
综合 HTML
以下是一个综合的 HTML 文件,它包含了多个 JavaScript 对象操作的示例,包括创建对象、操作属性、对象迭代、原型链、Proxy
、Reflect
、Object
方法等。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript对象综合案例</title>
</head>
<body>
<h1>JavaScript对象综合案例</h1>
<script>
// 创建对象
const person = {
firstName: "Kimi",
lastName: "Chat",
age: 30,
greet: function() {
console.log("Hello, " + this.firstName + " " + this.lastName);
}
};
// 访问和修改对象属性
console.log(person.firstName); // 输出 "Kimi"
person.firstName = "Moonshot";
console.log(person.firstName); // 输出 "Moonshot"
// 删除对象属性
delete person.age;
console.log(person.age); // 输出 "undefined"
// 枚举属性
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key + ": " + person[key]);
}
}
// Object 方法
console.log(Object.keys(person)); // 输出 ["firstName", "lastName", "greet"]
console.log(Object.values(person)); // 输出 ["Moonshot", "Chat", function()]
console.log(Object.entries(person)); // 输出 [["firstName", "Moonshot"], ["lastName", "Chat"], ["greet", function() {}]]
// 原型链
const proto = {
sayHello() {
console.log("Hello");
}
};
const obj = Object.create(proto);
obj.sayHello(); // 输出 "Hello"
// 动态属性名和方法
const prefix = "user";
const dynamicPerson = {};
dynamicPerson[prefix + 'Name'] = 'Kimi';
dynamicPerson[prefix + 'Age'] = 30;
console.log(dynamicPerson.userName); // 输出 "Kimi"
console.log(dynamicPerson.userAge); // 输出 30
// 对象的复制
const original = { a: 1, b: { c: 2 } };
const copied = { ...original };
copied.b.c = 4;
console.log(original); // { a: 1, b: { c: 2 } }
console.log(copied); // { a: 1, b: { c: 4 } }
// Proxy 和 Reflect
const proxyPerson = new Proxy(person, {
get(target, property, receiver) {
if (property === 'name') {
return `Mr. ${Reflect.get(target, property, receiver)}`;
}
return Reflect.get(target, property, receiver);
}
});
console.log(proxyPerson.name); // 输出 "Mr. Moonshot"
// Object.freeze() 和 Object.seal()
const frozenObj = Object.freeze({ a: 1 });
frozenObj.a = 2; // 无效,frozenObj.a 仍然是 1
const sealedObj = Object.seal({ a: 1, b: 2 });
sealedObj.c = 3; // 无效,属性 c 不会被添加
delete sealedObj.a; // 无效,属性 a 不会被删除
// Object.getOwnPropertyDescriptor()
const descriptor = Object.getOwnPropertyDescriptor(proxyPerson, 'name');
console.log(descriptor);
// Object.setPrototypeOf()
const newProto = { newMethod() { console.log('New Method'); } };
Object.setPrototypeOf(obj, newProto);
obj.newMethod(); // 输出 'New Method'
// Object.hasOwn()
const hasOwn = Object.hasOwn(person, 'firstName');
console.log(hasOwn); // 输出 true
// JSON.stringify() 的高级用法
const jsonString = JSON.stringify(person, (key, value) => {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
});
console.log(jsonString);
// Date 对象和时间操作
const now = new Date();
console.log(now.getFullYear());
console.log(now.getMonth());
console.log(now.getDate());
console.log(now.getTime());
// Math 对象和数值操作
console.log(Math.PI);
console.log(Math.sqrt(16));
console.log(Math.pow(2, 3));
console.log(Math.random());
// Array 对象和数组方法
const arr = [1, 2, 3, 4, 5];
console.log(arr.map(x => x * 2));
console.log(arr.filter(x => x > 2));
console.log(arr.reduce((acc, x) => acc + x, 0));
</script>
</body>
</html>
这个 HTML 文件包含了多个 JavaScript 对象操作的示例,每个示例都有相应的注释说明。你可以将这个代码复制到本地的 HTML 文件中,然后在浏览器中打开它,查看控制台输出的结果。这些示例涵盖了 JavaScript 对象的创建、操作、迭代、原型链、Proxy
、Reflect
、Object
方法等多个方面,帮助你全面了解 JavaScript 对象的用法。
10.4 JavaScript事件
10.4.1 事件及事件处理
在 JavaScript 中,事件处理是实现用户与网页交互的核心机制。以下是事件处理的基本概念和方法:
1. 事件处理概述
事件处理涉及到以下几个关键概念:
- 事件:用户或浏览器触发的动作,如点击、按键、页面加载等。
- 事件处理函数:当事件发生时执行的函数。
- 事件监听器:绑定在特定事件上的事件处理函数。
2. 事件处理函数
事件处理函数是当事件被触发时执行的函数。它们可以内联定义,也可以作为外部函数引用。
内联定义:
html
<button onclick="alert('Hello, World!');">点击我</button>
外部函数引用:
html
<button id="myButton">点击我</button>
<script>
function showAlert() {
alert('Hello, World!');
}
document.getElementById('myButton').onclick = showAlert;
</script>
3. 事件监听器
事件监听器是绑定到特定事件的函数。它们可以通过 addEventListener
方法添加到元素上。
案例:
javascript
const button = document.getElementById('myButton');
button.addEventListener('click', function(event) {
alert('按钮被点击了!');
});
4. 事件对象
事件对象包含了关于事件的详细信息,如事件类型、目标元素、鼠标位置等。它作为参数传递给事件处理函数。
案例:
javascript
const button = document.getElementById('myButton');
button.addEventListener('click', function(event) {
console.log(event.type); // "click"
console.log(event.target); // 触发事件的按钮元素
});
5. 阻止默认行为
在某些情况下,你可能想要阻止事件的默认行为,如阻止链接的默认导航行为。
案例:
javascript
const link = document.getElementById('myLink');
link.addEventListener('click', function(event) {
event.preventDefault();
alert('链接被点击了,但导航被阻止了!');
});
6. 事件传播
事件传播分为三个阶段:
- 捕获阶段:事件从文档根节点向目标节点传播。
- 目标阶段:事件到达目标节点。
- 冒泡阶段:事件从目标节点向文档根节点传播。
你可以通过 addEventListener
的第三个参数来指定监听器是在捕获阶段还是冒泡阶段触发。
案例(捕获阶段):
javascript
const div = document.getElementById('myDiv');
div.addEventListener('click', function(event) {
console.log('捕获阶段');
}, true); // true 表示在捕获阶段触发
7. 移除事件监听器
如果不再需要监听某个事件,可以使用 removeEventListener
方法来移除监听器。
案例:
javascript
const button = document.getElementById('myButton');
const handleClick = function() {
alert('按钮被点击了!');
};
button.addEventListener('click', handleClick);
// 稍后移除监听器
button.removeEventListener('click', handleClick);
8. 事件委托
事件委托是一种技术,它利用了事件冒泡的原理,通过在父元素上设置监听器来管理多个子元素的事件。这种方法可以减少内存的使用,并提高性能。
案例:
javascript
const list = document.getElementById('myList');
list.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
alert('列表项被点击了!');
}
});
通过这些事件处理的概念和方法,你可以创建更加动态和交互式的网页。事件处理是 JavaScript 中非常重要的一部分,它们使得网页能够响应用户的操作。
综合案例:JavaScript 事件处理
以下是一个综合案例,展示了如何在 HTML 页面中使用 JavaScript 事件处理。这个案例包括了事件监听器的添加、事件委托、阻止默认行为、事件对象的使用等。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript 事件处理综合案例</title>
<style>
#eventList {
list-style-type: none;
padding: 0;
}
#eventList li {
cursor: pointer;
padding: 5px;
border: 1px solid #ccc;
margin-bottom: 5px;
}
</style>
</head>
<body>
<h1>JavaScript 事件处理综合案例</h1>
<ul id="eventList">
<li>列表项 1</li>
<li>列表项 2</li>
<li>列表项 3</li>
</ul>
<button id="addListItem">添加列表项</button>
<script>
// 获取列表和按钮元素
const eventList = document.getElementById('eventList');
const addListItemButton = document.getElementById('addListItem');
// 添加点击事件监听器到列表项
eventList.addEventListener('click', function(event) {
const target = event.target;
if (target.tagName === 'LI') {
alert('列表项被点击了:' + target.textContent);
}
});
// 使用事件委托技术
eventList.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
event.target.style.backgroundColor = '#f0f0f0';
}
}, false);
// 添加按钮点击事件监听器
addListItemButton.addEventListener('click', function() {
const newListItem = document.createElement('li');
newListItem.textContent = '新列表项';
eventList.appendChild(newListItem);
});
// 阻止默认行为示例
const link = document.createElement('a');
link.href = '#';
link.textContent = '点击我';
link.addEventListener('click', function(event) {
event.preventDefault();
alert('链接被点击了,但导航被阻止了!');
});
document.body.appendChild(link);
</script>
</body>
</html>
案例说明:
-
事件监听器:为
eventList
添加了两个点击事件监听器,一个用于显示点击的列表项文本,另一个使用事件委托技术来改变被点击列表项的背景颜色。 -
事件委托:通过在父元素
eventList
上设置监听器,管理所有子元素li
的点击事件,这是事件委托的示例。 -
阻止默认行为:创建了一个链接元素,并通过事件监听器阻止了其默认的导航行为,点击时会弹出一个警告框。
-
动态元素的事件监听:通过按钮点击事件,动态添加新的列表项到页面中,新添加的列表项也能够响应点击事件,这是由于事件委托的使用。
这个综合案例展示了 JavaScript 事件处理的多个方面,包括事件监听器的添加、事件委托、阻止默认行为等,有助于理解事件处理在实际网页开发中的应用。
10.4.2 常用事件
综合案例:常用事件的应用
以下是一个 HTML 页面的示例,它展示了如何使用一些常用事件:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>常用事件综合案例</title>
<style>
#tooltip {
display: none;
position: absolute;
border: 1px solid #333;
background-color: #fff;
padding: 5px;
}
</style>
</head>
<body>
<h1>常用事件综合案例</h1>
<button id="myButton">点击我</button>
<input type="text" id="myInput" placeholder="输入文本">
<div id="tooltip">这是一个工具提示</div>
<script>
const button = document.getElementById('myButton');
const input = document.getElementById('myInput');
const tooltip = document.getElementById('tooltip');
// 点击事件
button.addEventListener('click', function() {
alert('按钮被点击了!');
});
// 输入事件
input.addEventListener('input', function() {
console.log('输入内容:' + input.value);
});
// 鼠标悬停事件
button.addEventListener('mouseover', function() {
tooltip.style.display = 'block';
});
button.addEventListener('mouseout', function() {
tooltip.style.display = 'none';
});
// 键盘事件
input.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
alert('你按下了回车键!');
}
});
</script>
</body>
</html>
案例说明:
-
点击事件:当用户点击按钮时,会弹出一个警告框。
-
输入事件:当用户在文本输入框中输入文本时,会在控制台显示输入的内容。
-
鼠标悬停事件:当鼠标悬停在按钮上时,会显示一个工具提示;当鼠标离开按钮时,工具提示会隐藏。
-
键盘事件:当用户在文本输入框中按下回车键时,会弹出一个警告框。
这个案例展示了如何在实际的 HTML 页面中使用 JavaScript 来处理用户交互和动态更新页面内容。通过这些常用事件,你可以创建更加丰富和响应式的用户体验。
10.4.3 事件应用举例
在这一节中,我们将通过几个具体的应用案例来展示如何使用 JavaScript 事件来增强网页的交互性。这些案例将涵盖表单处理、动态内容更新、用户交互反馈等常见场景。
案例 1: 表单验证与提交
在这个案例中,我们将创建一个简单的表单,当用户提交表单时,我们将验证输入并给予反馈。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单验证与提交</title>
</head>
<body>
<form id="myForm">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
<button type="submit">提交</button>
</form>
<p id="message"></p>
<script>
const form = document.getElementById('myForm');
const message = document.getElementById('message');
form.addEventListener('submit', function(event) {
event.preventDefault(); // 阻止表单默认提交行为
const username = document.getElementById('username').value;
if (username.trim() === '') {
message.textContent = '用户名不能为空';
} else {
message.textContent = '欢迎, ' + username;
}
});
</script>
</body>
</html>
案例 2: 动态内容更新
这个案例展示了如何根据用户的输入动态更新页面内容。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动态内容更新</title>
</head>
<body>
<input type="text" id="dynamicInput" placeholder="输入内容">
<p id="dynamicContent"></p>
<script>
const input = document.getElementById('dynamicInput');
const content = document.getElementById('dynamicContent');
input.addEventListener('input', function() {
content.textContent = '你输入了: ' + input.value;
});
</script>
</body>
</html>
案例 3: 图片轮播
这个案例创建了一个简单的图片轮播功能,用户可以通过点击按钮来切换图片。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片轮播</title>
</head>
<body>
<img id="slideShow" src="image1.jpg" alt="图片1">
<button onclick="nextSlide()">下一张</button>
<script>
let currentSlide = 0;
const images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
const slideShow = document.getElementById('slideShow');
function nextSlide() {
currentSlide = (currentSlide + 1) % images.length;
slideShow.src = images[currentSlide];
}
</script>
</body>
</html>
案例 4: 阻止链接默认行为
这个案例展示了如何使用 JavaScript 阻止链接的默认导航行为,并执行自定义操作。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止链接默认行为</title>
</head>
<body>
<a href="https://example.com" id="myLink">点击我</a>
<script>
const link = document.getElementById('myLink');
link.addEventListener('click', function(event) {
event.preventDefault();
alert('链接被点击了,但导航被阻止了!');
});
</script>
</body>
</html>
这些案例展示了 JavaScript 事件在实际网页开发中的应用,包括表单处理、动态内容更新、图片轮播和阻止链接默认行为等。通过这些示例,你可以更好地理解如何利用事件来提升用户体验和实现网页的动态交互。
综合案例--------轮播示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>轮播图示例</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
text-decoration: none;
}
body {
padding: 20px;
}
#container {
position: relative;
width: 600px;
height: 400px;
border: 1px solid #333;
overflow: hidden;
margin-left: auto;
margin-right: auto;
}
#list {
position: absolute;
z-index: 1;
width: 4200px;
height: 400px;
}
#list img {
float: left;
width: 600px;
height: 400px;
}
#buttons {
position: absolute;
left: 250px;
bottom: 20px;
z-index: 2;
height: 10px;
width: 100px;
}
#buttons span {
float: left;
margin-right: 5px;
width: 10px;
height: 10px;
border: 1px solid #fff;
border-radius: 50%;
background: #333;
cursor: pointer;
}
#buttons span.on {
background: orangered;
}
.arrow {
position: absolute;
top: 180px;
z-index: 2;
display: none;
width: 40px;
height: 40px;
font-size: 36px;
font-weight: bold;
line-height: 39px;
text-align: center;
color: #fff;
background-color: rgba(0, 0, 0, .3);
cursor: pointer;
}
.arrow:hover {
background-color: rgba(0, 0, 0, .7);
}
#container:hover .arrow {
display: block;
}
#prev {
left: 20px;
}
#next {
right: 20px;
}
</style>
<script type="text/javascript">
window.onload = function() {
var container = document.getElementById('container');
var list = document.getElementById('list');
var buttons = document.getElementById('buttons').getElementsByTagName('span');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
var index = 1;
var timer;
function animate(offset) {
var newLeft = parseInt(list.style.left) + offset;
list.style.left = newLeft + 'px';
if (newLeft > -600) {
list.style.left = -3000 + 'px';
}
if (newLeft < -3000) {
list.style.left = -600 + 'px';
}
}
function play() {
timer = setInterval(function() {
next.onclick();
}, 2000);
}
function stop() {
clearInterval(timer);
}
function buttonsShow() {
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].className == "on") {
buttons[i].className = "";
}
}
buttons[index - 1].className = "on";
}
prev.onclick = function() {
index -= 1;
if (index < 1) {
index = 5;
}
buttonsShow();
animate(600);
};
next.onclick = function() {
index += 1;
if (index > 5) {
index = 1;
}
animate(-600);
buttonsShow();
};
for (var i = 0; i < buttons.length; i++) {
(function(i) {
buttons[i].onclick = function() {
var clickIndex = parseInt(this.getAttribute('index'));
var offset = 600 * (index - clickIndex);
animate(offset);
index = clickIndex;
buttonsShow();
};
})(i);
}
container.onmouseover = stop;
container.onmouseout = play;
play();
}
</script>
</head>
<body>
<div id="container">
<div id="list" style="left: -600px;">
<img src="img/p5.jpg" alt="5" />
<img src="img/p1.jpg" alt="1" />
<img src="img/p2.jpg" alt="2" />
<img src="img/p3.jpg" alt="3" />
<img src="img/p4.jpg" alt="4" />
<img src="img/p5.jpg" alt="5" />
<img src="img/p1.jpg" alt="1" />
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:void(0);" id="prev" class="arrow"><</a>
<a href="javascript:void(0);" id="next" class="arrow">></a>
</div>
</body>
</html>