你不知道的JS(下):深入JS(上)

目录

  1. JavaScript 的运行机制
  2. 作用域和闭包
  3. 原型与继承
  4. 异步编程
  5. 模块化开发
  6. 错误处理
  7. 性能优化
  8. 总结

JavaScript 的运行机制

JavaScript 是一种单线程语言,这意味着它在任何时刻只会执行一个任务。为了提升效率,JavaScript 引入了事件循环和调用栈的概念。

1.1 调用栈

调用栈是一个后进先出(LIFO)的数据结构。JavaScript 执行时会将执行上下文放入调用栈中。

javascriptCopy Code
function first() { second(); console.log('First'); } function second() { console.log('Second'); } first(); // 输出: // Second // First

在这个例子中,first 函数被调用,将 second 添加到调用栈中。然后 second 函数执行,输出 'Second',再返回到 first,输出 'First'。

1.2 事件循环

事件循环用于处理异步操作。在JavaScript中,当遇到异步操作时,不会阻塞主线程,而是将其放入一个任务队列,待调用栈为空时再执行。

javascriptCopy Code
console.log('Start'); setTimeout(() => { console.log('Timeout'); }, 0); console.log('End'); // 输出: // Start // End // Timeout

在这个例子中,尽管 setTimeout 的延迟为 0 毫秒,它仍然会在主线程完成后执行。

作用域和闭包

2.1 作用域

作用域是变量的可访问范围。在 JavaScript 中有全局作用域和局部作用域。

javascriptCopy Code
let globalVar = 'I am a global variable'; function myFunction() { let localVar = 'I am a local variable'; console.log(globalVar); // 可以访问全局变量 console.log(localVar); // 可以访问局部变量 } myFunction(); // 输出: // I am a global variable // I am a local variable

2.2 闭包

闭包是指一个函数可以“记住”并访问它定义时的词法作用域,即使这个函数是在其词法作用域之外执行的。

javascriptCopy Code
function outer() { let count = 0; return function inner() { count++; console.log(count); }; } const increment = outer(); increment(); // 输出:1 increment(); // 输出:2

在这个例子中,inner 函数形成了一个闭包,可以访问 outer 函数中的 count 变量。

原型与继承

3.1 原型

每个 JavaScript 对象都有一个原型属性,指向另一个对象。通过原型链,JavaScript 实现了继承。

javascriptCopy Code
function Animal(name) { this.name = name; } Animal.prototype.speak = function () { console.log(`${this.name} makes a noise.`); }; const dog = new Animal('Dog'); dog.speak(); // 输出:Dog makes a noise.

3.2 继承

可以通过原型链实现对象的继承。

javascriptCopy Code
function Dog(name) { Animal.call(this, name); // 调用父构造函数 } Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; Dog.prototype.speak = function () { console.log(`${this.name} barks.`); }; const dog = new Dog('Rex'); dog.speak(); // 输出:Rex barks.

在这个例子中,Dog 继承了 Animal 的属性和方法。

异步编程

JavaScript 提供多种方式来处理异步编程,包括回调、Promise 和 async/await。

4.1 回调

回调是最基本的异步处理方式。

javascriptCopy Code
function fetchData(callback) { setTimeout(() => { callback('Data received'); }, 1000); } fetchData((data) => { console.log(data); // 输出:Data received });

4.2 Promise

Promise 提供了一种更强大且易于管理的异步编程方式。

javascriptCopy Code
function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve('Data received'); }, 1000); }); } fetchData().then((data) => { console.log(data); // 输出:Data received });

4.3 Async/Await

Async/Await 是基于 Promise 的语法糖,更加简洁易读。

javascriptCopy Code
async function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve('Data received'); }, 1000); }); } (async () => { const data = await fetchData(); console.log(data); // 输出:Data received })();

模块化开发

模块化是将代码分割成独立模块的过程,方便管理和复用。

5.1 ES6 模块

ES6 引入了模块化的标准。

javascriptCopy Code
// math.js export function add(x, y) { return x + y; } // main.js import { add } from './math.js'; console.log(add(2, 3)); // 输出:5

5.2 CommonJS

Node.js 使用 CommonJS 模块化。

javascriptCopy Code
// math.js exports.add = function (x, y) { return x + y; }; // main.js const math = require('./math'); console.log(math.add(2, 3)); // 输出:5

错误处理

错误处理是编写健壮代码的重要部分。

6.1 try...catch

使用 try...catch 捕获同步代码中的错误。

javascriptCopy Code
try { throw new Error('Something went wrong'); } catch (error) { console.error(error.message); // 输出:Something went wrong }

6.2 Promise 错误处理

处理 Promise 中的错误。

javascriptCopy Code
fetchData() .then((data) => { console.log(data); }) .catch((error) => { console.error(error); });

6.3 Async/Await 错误处理

在 async 函数中可以使用 try...catch 处理错误。

javascriptCopy Code
(async () => { try { const data = await fetchData(); console.log(data); } catch (error) { console.error(error); } })();

性能优化

提高 JavaScript 性能的技巧包括减少 DOM 操作、使用节流和防抖等。

7.1 减少 DOM 操作

DOM 操作是昂贵的,应该尽量减少。

javascriptCopy Code
const list = document.createElement('ul'); for (let i = 0; i < 1000; i++) { const item = document.createElement('li'); item.textContent = `Item ${i}`; list.appendChild(item); } document.body.appendChild(list);

7.2 节流和防抖

节流和防抖用于限制函数调用频率。

防抖

javascriptCopy Code
function debounce(func, delay) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), delay); }; }

节流

javascriptCopy Code
function throttle(func, limit) { let lastFunc; let lastRan; return function (...args) { if (!lastRan) { func.apply(this, args); lastRan = Date.now(); } else { clearTimeout(lastFunc); lastFunc = setTimeout(() => { if (Date.now() - lastRan >= limit) { func.apply(this, args); lastRan = Date.now(); } }, limit - (Date.now() - lastRan)); } }; }

总结

JavaScript 是一种功能强大的编程语言,掌握其深入知识对于编写高效、可维护的代码至关重要。本文涵盖了 JavaScript 的运行机制、作用域与闭包、原型与继承、异步编程、模块化开发、错误处理及性能优化等内容。希望对你深入理解 JavaScript 有所帮助。