JavaScript学习教程,从入门到精通,JavaScript 基础语法全面指南(5)

news2025/4/10 17:42:52

JavaScript 基础语法全面指南

一、JavaScript 基本概念

JavaScript 是一种轻量级的解释型或即时编译型的编程语言,主要用于网页开发,为网页添加交互功能。

1.1 JavaScript 的特点

  • 解释型语言:不需要编译,由 JavaScript 引擎直接解释执行
  • 动态类型:变量类型在运行时确定
  • 基于原型:使用原型继承而非类继承
  • 多范式:支持面向对象、函数式和命令式编程风格
  • 单线程:使用事件循环和回调机制处理并发

1.2 JavaScript 的执行方式

JavaScript 可以通过以下方式执行:

  1. HTML 文件中的 <script> 标签

    <script>
      console.log("Hello, World!");
    </script>
    
  2. 外部 JavaScript 文件

    <script src="script.js"></script>
    
  3. 浏览器控制台:直接在浏览器开发者工具的控制台中输入 JavaScript 代码

  4. Node.js 环境:通过命令行执行 .js 文件

二、标识符

标识符是用来标识变量、函数、属性或参数的名称。

2.1 标识符命名规则

  • 必须以字母、下划线 (_) 或美元符号 ($) 开头
  • 后续字符可以是字母、数字、下划线或美元符号
  • 区分大小写
  • 不能使用关键字或保留字作为标识符

2.2 合法的标识符示例

// 合法的标识符
let userName;
let _privateVariable;
let $element;
let camelCaseName;
let MAX_VALUE;

// 不合法的标识符
// let 123abc;      // 不能以数字开头
// let my-variable; // 不能包含连字符
// let function;    // 不能使用关键字

2.3 命名约定

  • 驼峰命名法 (camelCase):变量和函数名通常使用小驼峰

    let firstName = "John";
    function getUserInfo() {}
    
  • 帕斯卡命名法 (PascalCase):构造函数或类名通常使用大驼峰

    class UserProfile {}
    function Person() {}
    
  • 常量命名:全大写,单词间用下划线分隔

    const MAX_HEIGHT = 100;
    const API_KEY = "abc123";
    
  • 私有成员:以下划线开头(约定而非强制)

    class User {
      constructor() {
        this._privateData = "secret";
      }
    }
    

三、关键字和保留字

3.1 JavaScript 关键字

关键字是 JavaScript 语言中有特殊含义的单词,不能用作标识符。

ECMAScript 2020 (ES11) 关键字列表

break       case        catch       class       const
continue    debugger    default     delete      do
else        export      extends     false       finally
for         function    if          import      in
instanceof  new         null        return      super
switch      this        throw       true        try
typeof      var         void        while       with
yield

3.2 未来保留字

这些单词虽然目前没有特殊功能,但被保留以备将来使用:

enum       implements  interface   let        package
private    protected   public      static     await

3.3 严格模式下的保留字

在严格模式下 ("use strict"),这些单词也不能用作标识符:

arguments  eval

3.4 关键字使用示例

// 变量声明
let x = 10;
const PI = 3.14;

// 条件语句
if (x > 5) {
  console.log("x is greater than 5");
} else {
  console.log("x is 5 or less");
}

// 循环
for (let i = 0; i < 5; i++) {
  console.log(i);
}

// 函数
function add(a, b) {
  return a + b;
}

// 类
class Person {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

// try-catch
try {
  // 可能出错的代码
  JSON.parse("{invalid json}");
} catch (error) {
  console.error("Parsing error:", error);
}

四、注释

注释是代码中不会被执行的文本,用于解释代码的功能和目的。

4.1 单行注释

// 开头,直到行尾的内容都是注释。

// 这是一个单行注释
let age = 25; // 声明一个年龄变量

4.2 多行注释

/* 开头,以 */ 结尾,中间的内容都是注释。

/*
 * 这是一个多行注释
 * 可以跨越多行
 * 常用于文件或函数的说明
 */
function calculateTotal(price, quantity) {
  /* 
   * 计算总价
   * 参数: price - 单价
   *      quantity - 数量
   * 返回: 总价
   */
  return price * quantity;
}

4.3 JSDoc 注释

一种特殊的注释格式,用于生成文档。

/**
 * 计算两个数字的和
 * @param {number} a 第一个数字
 * @param {number} b 第二个数字
 * @returns {number} 两个数字的和
 */
function sum(a, b) {
  return a + b;
}

4.4 注释的最佳实践

  1. 解释为什么,而不是什么

    // 不好的注释
    let x = 5; // 设置x为5
    
    // 好的注释
    let retryCount = 5; // 最多重试5次,超过则放弃连接
    
  2. 避免无意义的注释

    // 不好的注释
    // 增加i的值
    i++;
    
  3. 使用注释标记待办事项

    // TODO: 需要优化这个算法
    function slowAlgorithm() {
      // ...
    }
    
  4. 注释掉代码时要说明原因

    // 暂时禁用此功能,等待API更新
    // function oldFeature() {
    //   // ...
    // }
    

五、变量和常量

5.1 变量声明

JavaScript 有三种变量声明方式:

  1. var (ES5 及之前)

    var name = "John";
    
  2. let (ES6+ 块级作用域变量)

    let age = 30;
    
  3. const (ES6+ 块级作用域常量)

    const PI = 3.14159;
    

5.2 变量声明示例

// 使用 var (函数作用域)
function varExample() {
  if (true) {
    var x = 10;
  }
  console.log(x); // 10, var 是函数作用域
}

// 使用 let (块级作用域)
function letExample() {
  if (true) {
    let y = 20;
    console.log(y); // 20
  }
  // console.log(y); // 报错: y is not defined
}

// 使用 const (块级作用域常量)
const PI = 3.14159;
// PI = 3.14; // 报错: Assignment to constant variable

// const 声明的对象属性可以修改
const person = {
  name: "John"
};
person.name = "Jane"; // 允许
// person = {}; // 报错

5.3 变量提升 (Hoisting)

JavaScript 中,var 声明会被提升到函数或全局作用域的顶部。

console.log(a); // undefined (不会报错)
var a = 10;

// 相当于:
// var a;
// console.log(a);
// a = 10;

// let 和 const 不会被提升
console.log(b); // 报错: Cannot access 'b' before initialization
let b = 20;

六、数据类型

JavaScript 是动态类型语言,有 7 种基本数据类型和 1 种复杂数据类型。

6.1 基本数据类型 (原始类型)

  1. number - 数字

    let age = 25;
    let price = 99.99;
    let infinity = Infinity;
    let nan = NaN; // Not a Number
    
  2. string - 字符串

    let name = "John";
    let greeting = 'Hello';
    let template = `Hello, ${name}`; // 模板字符串
    
  3. boolean - 布尔值

    let isActive = true;
    let isCompleted = false;
    
  4. null - 空值

    let emptyValue = null;
    
  5. undefined - 未定义

    let notDefined;
    console.log(notDefined); // undefined
    
  6. symbol (ES6+) - 唯一标识符

    let id = Symbol("id");
    
  7. bigint (ES2020+) - 大整数

    const bigNumber = 123456789012345678901234567890n;
    

6.2 复杂数据类型

  1. object - 对象

    let person = {
      name: "John",
      age: 30
    };
    
    let colors = ["red", "green", "blue"]; // 数组也是对象
    let date = new Date(); // 日期对象
    

6.3 类型检测

// typeof 操作符
console.log(typeof 42);        // "number"
console.log(typeof "hello");   // "string"
console.log(typeof true);      // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null);      // "object" (历史遗留问题)
console.log(typeof {});        // "object"
console.log(typeof []);        // "object"
console.log(typeof Symbol());  // "symbol"
console.log(typeof 10n);       // "bigint"

// instanceof 检查对象类型
console.log([] instanceof Array);    // true
console.log(new Date() instanceof Date); // true

// Array.isArray() 检查数组
console.log(Array.isArray([]));      // true
console.log(Array.isArray({}));      // false

七、运算符

7.1 算术运算符

let x = 10, y = 3;

console.log(x + y);  // 13
console.log(x - y);  // 7
console.log(x * y);  // 30
console.log(x / y);  // 3.333...
console.log(x % y);  // 1 (取余)
console.log(x ** y); // 1000 (指数)
console.log(++x);    // 11 (前缀递增)
console.log(y--);    // 3 (后缀递减)

7.2 赋值运算符

let a = 10;

a += 5;  // a = a + 5 → 15
a -= 3;  // a = a - 3 → 12
a *= 2;  // a = a * 2 → 24
a /= 4;  // a = a / 4 → 6
a %= 5;  // a = a % 5 → 1
a **= 3; // a = a ** 3 → 1

7.3 比较运算符

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
console.log(5 >= 5);     // true
console.log(5 <= 4);     // false

7.4 逻辑运算符

// 逻辑与 (&&)
console.log(true && false); // false
console.log(5 && 0);        // 0

// 逻辑或 (||)
console.log(true || false); // true
console.log(0 || "default"); // "default"

// 逻辑非 (!)
console.log(!true);         // false
console.log(!0);            // true

// 空值合并运算符 (??) (ES2020)
console.log(null ?? "default"); // "default"
console.log(0 ?? "default");    // 0

7.5 三元运算符

let age = 20;
let status = (age >= 18) ? "成人" : "未成年";
console.log(status); // "成人"

八、控制流程

8.1 条件语句

// if-else
let hour = 14;

if (hour < 12) {
  console.log("上午好");
} else if (hour < 18) {
  console.log("下午好");
} else {
  console.log("晚上好");
}

// switch
let day = 3;
let dayName;

switch (day) {
  case 1:
    dayName = "星期一";
    break;
  case 2:
    dayName = "星期二";
    break;
  case 3:
    dayName = "星期三";
    break;
  default:
    dayName = "未知";
}
console.log(dayName); // "星期三"

8.2 循环语句

// for 循环
for (let i = 0; i < 5; i++) {
  console.log(i); // 0, 1, 2, 3, 4
}

// while 循环
let j = 0;
while (j < 5) {
  console.log(j); // 0, 1, 2, 3, 4
  j++;
}

// do-while 循环
let k = 0;
do {
  console.log(k); // 0, 1, 2, 3, 4
  k++;
} while (k < 5);

// for...of 循环 (ES6+)
let colors = ["red", "green", "blue"];
for (let color of colors) {
  console.log(color); // "red", "green", "blue"
}

// for...in 循环 (遍历对象属性)
let person = {name: "John", age: 30};
for (let key in person) {
  console.log(key + ": " + person[key]); // "name: John", "age: 30"
}

8.3 控制循环

// break
for (let i = 0; i < 10; i++) {
  if (i === 5) break;
  console.log(i); // 0, 1, 2, 3, 4
}

// continue
for (let i = 0; i < 5; i++) {
  if (i === 2) continue;
  console.log(i); // 0, 1, 3, 4
}

// 标签 (label)
outerLoop: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) break outerLoop;
    console.log(`i=${i}, j=${j}`);
  }
}
// 输出:
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0

九、函数

9.1 函数声明

// 函数声明
function greet(name) {
  return `Hello, ${name}!`;
}

// 函数表达式
const greet = function(name) {
  return `Hello, ${name}!`;
};

// 箭头函数 (ES6+)
const greet = (name) => `Hello, ${name}!`;

// 调用函数
console.log(greet("John")); // "Hello, John!"

9.2 函数参数

// 默认参数 (ES6+)
function greet(name = "Guest") {
  return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"

// 剩余参数 (ES6+)
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6

// 解构参数
function printUser({name, age}) {
  console.log(`${name} is ${age} years old`);
}
printUser({name: "John", age: 30}); // "John is 30 years old"

9.3 高阶函数

// 函数作为参数
function operate(a, b, operation) {
  return operation(a, b);
}

const add = (x, y) => x + y;
const multiply = (x, y) => x * y;

console.log(operate(5, 3, add));      // 8
console.log(operate(5, 3, multiply)); // 15

// 函数作为返回值
function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = createMultiplier(2);
console.log(double(5)); // 10

十、对象和数组

10.1 对象

// 对象字面量
let person = {
  name: "John",
  age: 30,
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

// 访问属性
console.log(person.name); // "John"
console.log(person["age"]); // 30
person.greet(); // "Hello, my name is John"

// 添加/修改属性
person.job = "Developer";
person.age = 31;

// 删除属性
delete person.job;

// 对象解构 (ES6+)
let {name, age} = person;
console.log(name, age); // "John" 31

10.2 数组

// 数组字面量
let colors = ["red", "green", "blue"];

// 访问元素
console.log(colors[0]); // "red"

// 修改元素
colors[1] = "yellow";

// 数组方法
colors.push("black");   // 末尾添加
colors.pop();           // 移除最后一个
colors.unshift("white"); // 开头添加
colors.shift();         // 移除第一个

// 数组解构 (ES6+)
let [firstColor, secondColor] = colors;
console.log(firstColor, secondColor); // "red" "yellow"

// 常用数组方法
let numbers = [1, 2, 3, 4, 5];

// map
let doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// filter
let evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]

// reduce
let sum = numbers.reduce((total, n) => total + n, 0);
console.log(sum); // 15

十一、错误处理

11.1 try-catch-finally

try {
  // 可能出错的代码
  let result = riskyOperation();
  console.log(result);
} catch (error) {
  // 处理错误
  console.error("An error occurred:", error.message);
} finally {
  // 无论是否出错都会执行
  console.log("Operation attempted");
}

function riskyOperation() {
  if (Math.random() > 0.5) {
    throw new Error("Something went wrong");
  }
  return "Success";
}

11.2 自定义错误

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

function validateInput(input) {
  if (!input) {
    throw new ValidationError("Input cannot be empty");
  }
}

try {
  validateInput("");
} catch (error) {
  if (error instanceof ValidationError) {
    console.error("Validation failed:", error.message);
  } else {
    console.error("Unknown error:", error);
  }
}

十二、现代 JavaScript 特性 (ES6+)

12.1 模板字符串

let name = "John";
let age = 30;

// 传统方式
let greeting = "Hello, my name is " + name + " and I'm " + age + " years old.";

// 模板字符串
let greeting = `Hello, my name is ${name} and I'm ${age} years old.`;

// 多行字符串
let message = `
  Dear ${name},
  
  Thank you for your order.
  We'll process it shortly.
  
  Regards,
  The Team
`;

12.2 解构赋值

// 数组解构
let [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a, b, rest); // 1, 2, [3, 4, 5]

// 对象解构
let {firstName, lastName} = {firstName: "John", lastName: "Doe"};
console.log(firstName, lastName); // "John", "Doe"

// 参数解构
function greet({name, age}) {
  console.log(`Hello ${name}, you are ${age} years old`);
}
greet({name: "Alice", age: 25});

12.3 展开运算符

// 数组展开
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

// 对象展开
let obj1 = {a: 1, b: 2};
let obj2 = {...obj1, c: 3}; // {a: 1, b: 2, c: 3}

// 函数参数展开
function sum(a, b, c) {
  return a + b + c;
}
let numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6

12.4 可选链 (Optional Chaining, ES2020)

let user = {
  profile: {
    name: "John",
    address: {
      city: "New York"
    }
  }
};

// 传统方式
let city = user && user.profile && user.profile.address && user.profile.address.city;

// 可选链
let city = user?.profile?.address?.city;
console.log(city); // "New York"

// 方法调用
let result = user.getAddress?.(); // 如果getAddress不存在则返回undefined

// 数组访问
let firstItem = arr?.[0];

12.5 空值合并运算符 (Nullish Coalescing, ES2020)

let value = 0;
let defaultValue = 42;

// 传统方式 (|| 的问题)
let result = value || defaultValue; // 42 (0被视为假值)

// 空值合并运算符
let result = value ?? defaultValue; // 0 (只有null/undefined才会使用默认值)

// 实际应用
function printMessage(text) {
  let message = text ?? "Default message";
  console.log(message);
}

printMessage(null);      // "Default message"
printMessage(undefined); // "Default message"
printMessage("Hello");   // "Hello"
printMessage("");        // ""
printMessage(0);         // 0

十三、模块化

13.1 ES6 模块

math.js:

// 导出单个值
export const PI = 3.14159;

// 导出函数
export function square(x) {
  return x * x;
}

// 默认导出
export default function multiply(a, b) {
  return a * b;
}

app.js:

// 导入默认导出
import multiply from './math.js';

// 导入命名导出
import { PI, square } from './math.js';

// 导入所有命名导出作为命名空间
import * as math from './math.js';

console.log(multiply(2, 3)); // 6
console.log(PI);            // 3.14159
console.log(square(4));     // 16
console.log(math.PI);       // 3.14159

13.2 CommonJS 模块 (Node.js)

math.js:

exports.PI = 3.14159;

exports.square = function(x) {
  return x * x;
};

module.exports = function multiply(a, b) {
  return a * b;
};

app.js:

const multiply = require('./math');
const { PI, square } = require('./math');

console.log(multiply(2, 3)); // 6
console.log(PI);            // 3.14159
console.log(square(4));     // 16

十四、Promise 和异步编程

14.1 Promise 基础

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = Math.random() > 0.3;
      if (success) {
        resolve("Data fetched successfully");
      } else {
        reject(new Error("Failed to fetch data"));
      }
    }, 1000);
  });
}

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error.message))
  .finally(() => console.log("Operation completed"));

14.2 async/await (ES2017)

async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
    return data;
  } catch (error) {
    console.error("Error:", error);
    throw error;
  }
}

// 调用async函数
getData().then(data => {
  console.log("Data received:", data);
});

14.3 Promise 实用方法

// Promise.all - 等待所有promise完成
Promise.all([
  fetch('/api/users'),
  fetch('/api/products')
])
.then(([users, products]) => {
  console.log("All data loaded");
})
.catch(error => {
  console.error("One of the requests failed");
});

// Promise.race - 第一个完成或拒绝的promise
Promise.race([
  fetch('/api/fast'),
  new Promise((_, reject) => 
    setTimeout(() => reject(new Error('Timeout')), 5000)
  )
])
.then(data => {
  console.log("Got data before timeout");
})
.catch(error => {
  console.error(error.message);
});

十五、类 (ES6)

15.1 类基础

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  // 实例方法
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
  
  // 静态方法
  static info() {
    console.log("This is a Person class");
  }
}

// 创建实例
const john = new Person("John", 30);
john.greet(); // "Hello, my name is John"
Person.info(); // "This is a Person class"

15.2 继承

class Student extends Person {
  constructor(name, age, grade) {
    super(name, age); // 调用父类构造函数
    this.grade = grade;
  }
  
  study() {
    console.log(`${this.name} is studying`);
  }
  
  // 方法重写
  greet() {
    console.log(`Hi, I'm ${this.name}, a student`);
  }
}

const alice = new Student("Alice", 20, "A");
alice.greet(); // "Hi, I'm Alice, a student"
alice.study(); // "Alice is studying"

15.3 Getter 和 Setter

class Temperature {
  constructor(celsius) {
    this.celsius = celsius;
  }
  
  get fahrenheit() {
    return this.celsius * 1.8 + 32;
  }
  
  set fahrenheit(value) {
    this.celsius = (value - 32) / 1.8;
  }
}

const temp = new Temperature(25);
console.log(temp.fahrenheit); // 77
temp.fahrenheit = 100;
console.log(temp.celsius); // 37.777...

十六、JavaScript 最佳实践

16.1 代码风格

  1. 一致的缩进:使用 2 或 4 个空格

  2. 分号:始终使用分号或始终不使用

  3. 引号:统一使用单引号或双引号

  4. 大括号位置

    // 好的
    if (condition) {
      // ...
    }
    
    // 不好的
    if (condition)
    {
      // ...
    }
    
  5. 命名约定:见前面的命名约定部分

16.2 避免全局变量

// 不好的做法
var globalVar = "I'm global";

// 好的做法
(function() {
  let localVar = "I'm local";
})();

// 或使用模块

16.3 使用严格模式

"use strict";

// 严格模式下会报错的行为
x = 10; // 未声明的变量
delete Object.prototype; // 删除不可删除的属性
function duplicateParam(a, a) {} // 重复参数名

16.4 性能优化

  1. 减少DOM操作

    // 不好的做法
    for (let i = 0; i < 100; i++) {
      document.getElementById('list').innerHTML += `<li>Item ${i}</li>`;
    }
    
    // 好的做法
    let html = '';
    for (let i = 0; i < 100; i++) {
      html += `<li>Item ${i}</li>`;
    }
    document.getElementById('list').innerHTML = html;
    
  2. 事件委托

    // 不好的做法
    document.querySelectorAll('.item').forEach(item => {
      item.addEventListener('click', handleClick);
    });
    
    // 好的做法
    document.getElementById('container').addEventListener('click', event => {
      if (event.target.classList.contains('item')) {
        handleClick(event);
      }
    });
    
  3. 避免不必要的计算

    // 不好的做法
    function isPrime(num) {
      for (let i = 2; i < num; i++) {
        if (num % i === 0) return false;
      }
      return num > 1;
    }
    
    // 好的做法 (缓存结果)
    const primeCache = {};
    function isPrime(num) {
      if (primeCache[num] !== undefined) return primeCache[num];
      
      for (let i = 2, max = Math.sqrt(num); i <= max; i++) {
        if (num % i === 0) {
          primeCache[num] = false;
          return false;
        }
      }
      primeCache[num] = num > 1;
      return primeCache[num];
    }
    

16.5 安全实践

  1. 避免eval

    // 非常危险
    eval(userInput);
    
    // 更好的选择
    Function('return ' + userInput)();
    
  2. 防止XSS

    // 不好的做法
    element.innerHTML = userInput;
    
    // 好的做法
    element.textContent = userInput;
    
  3. 验证输入

    function processInput(input) {
      if (typeof input !== 'string') {
        throw new TypeError('Expected string input');
      }
      // 处理输入
    }
    

十七、调试技巧

17.1 console 方法

// 基本日志
console.log("普通信息");

// 带样式的日志
console.log("%c带样式的文本", "color: red; font-weight: bold");

// 调试信息
console.debug("调试信息");

// 信息
console.info("提示信息");

// 警告
console.warn("警告信息");

// 错误
console.error("错误信息");

// 断言
console.assert(1 === 2, "1不等于2");

// 计数
console.count("counter");
console.count("counter");

// 分组
console.group("分组");
console.log("分组内信息");
console.groupEnd();

// 表格
console.table([{a:1, b:2}, {a:3, b:4}]);

// 计时
console.time("timer");
// 一些操作
console.timeEnd("timer");

// 堆栈跟踪
console.trace("调用堆栈");

17.2 debugger 语句

function problematicFunction() {
  let x = 10;
  debugger; // 执行到这里会暂停
  x += 5;
  return x;
}

17.3 错误处理

try {
  // 可能出错的代码
  JSON.parse("{invalid json}");
} catch (error) {
  console.error("Parsing error:", error);
  // 可以上报错误到服务器
  // reportError(error);
} finally {
  // 清理代码
}

十八、JavaScript 版本历史

版本年份重要特性
ES11997基础语法
ES21998小修订
ES31999try/catch, 正则表达式
ES52009JSON, 严格模式, 数组方法
ES6 (ES2015)2015let/const, 类, 模块, 箭头函数, Promise
ES20162016数组includes(), 指数运算符
ES20172017async/await, Object.values/entries
ES20182018Promise.finally, 展开运算符对象
ES20192019Array.flat, Object.fromEntries
ES20202020可选链, 空值合并, BigInt
ES20212021String.replaceAll, Promise.any
ES20222022类字段, 顶层await, 私有方法

十九、浏览器兼容性

19.1 特性检测

// 检查是否支持某个特性
if (typeof Promise !== 'undefined') {
  // 支持Promise
} else {
  // 不支持Promise
}

// 更复杂的检测
function isFeatureSupported() {
  try {
    new Function("(a = 0) => a");
    return true;
  } catch (err) {
    return false;
  }
}

19.2 Polyfill 和转译

  1. Babel:将现代 JavaScript 代码转译为旧版浏览器支持的代码
  2. Core-js:提供 JavaScript 标准库的 polyfill
  3. Polyfill.io:根据浏览器自动提供需要的 polyfill

19.3 兼容性资源

  • Can I use:查看浏览器对各种特性的支持情况
  • MDN 兼容性表格:MDN 文档中的兼容性信息
  • ECMAScript 兼容性表:详细的 ECMAScript 特性兼容性表格

二十、JavaScript 学习资源

20.1 官方文档

  • MDN JavaScript:最全面的 JavaScript 文档
  • ECMAScript 规范:官方语言规范
  • Node.js 文档:Node.js 相关 API

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码开发平台:飞帆制作网页并集成到自己的网页中

应用场景&#xff1a; 有时&#xff0c;我们的网页使用了某个模版&#xff0c;或者自己写的 html、css、javascript 代码。只是网页中的一部分使用飞帆来制作。这样的混合网页如何实现呢&#xff1f; 其实很容易&#xff0c;来体验一下飞帆提供的功能&#xff01; 还记得这个…

语法: result=log (x);

LOG( ) 语法: resultlog (x); 参数: x是一个浮点数; 返回值: result等于返回值,是一个浮点数; 功能: 该函数是用来计算浮点数x的自然对数(即ln x);如果x小于或等于0,或x太大,则行为没有定义; 注意:存在error挂起; 如果在编写程序里包含了errno.h头文件,则范围和等级…

Hibernate核心方法总结

Session中的核心方法梳理 1、save方法 这个方法表示将一个对象保存到数据库中&#xff0c;可以将一个不含OID的new出来的临时对象转换为一个处于Session缓存中具有OID的持久化对象。 需要注意的是&#xff1a;在save方法前设置OID是无效的但是也不会报错&#xff0c;在save方…

IntelliJ IDEA Maven 工具栏消失怎么办?

一、问题现象与背景 在使用 IntelliJ IDEA&#xff08;简称 IDEA&#xff09;开发 Maven 项目时&#xff0c;偶尔会遇到右侧或侧边栏的 Maven 工具栏&#xff08;显示依赖、生命周期等信息的窗口&#xff09;突然消失的情况。这可能影响开发者快速操作 Maven 构建、依赖管理等…

消息队列(kafka 与 rocketMQ)

为什么要使用消息队列?作用1: 削峰填谷(突发大请求量问题)作用2: 解耦(单一原则)作用3: 异步(减少处理时间) 如何选择消息队列(kafka&RocketMQ)成本功能性能选择 rocketMQ是参考kafka进行实现的为什么rocketMQ与kafka性能差距很大呢?kafka 的底层数据储存实现rocketMQ 的…

【STM32】Flash详解

【STM32】Flash详解 文章目录 【STM32】Flash详解1.Flash闪存概念1. 1核心区别&#xff1a;NOR Flash vs. NAND Flash1.2 为什么常说的“Flash”多指 NAND Flash&#xff1f;1.3技术细节对比(1) 存储单元结构(2) 应用场景(3) 可靠性要求 1.4总结 2.STM32内部的Flash2.1为什么是…

CV - 目标检测

物体检测 目标检测和图片分类的区别&#xff1a; 图像分类&#xff08;Image Classification&#xff09; 目的&#xff1a;图像分类的目的是识别出图像中主要物体的类别。它试图回答“图像是什么&#xff1f;”的问题。 输出&#xff1a;通常输出是一个标签或一组概率值&am…

node-modules-inspector 可视化node_modules

1、node_modules 每个vue的项目都有很多的依赖&#xff0c;有的是dev的&#xff0c;有的是生产的。 2、使用命令pnpx node-modules-inspector pnpx node-modules-inspector 3、node_modules可视化 4、在线体验 Node Modules Inspector 5、github地址 https://github.com/a…

远程服务器下载llama模型

适用于有防火墙不能直接从HF上下载的情况 然后&#xff0c;你可以克隆 Llama-3.1-8B-Instruct 模型&#xff1a; git clone https://你的用户名:你的访问令牌hf-mirror.com/meta-llama/Llama-3.1-8B-Instruct用户名&#xff0c;令牌来自huggingface官网 注意&#xff1a;要提…

2011-2019年各省地方财政金融监管支出数据

2011-2019年各省地方财政金融监管支出数据 1、时间&#xff1a;2007-2019年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区、年份、地方财政金融监管支出 4、范围&#xff1a;31省 5、指标说明&#xff1a;地方财政在金融监管方面的支出…

Java大厂面试题 -- JVM 优化进阶之路:从原理到实战的深度剖析(2)

最近佳作推荐&#xff1a; Java大厂面试题 – 深度揭秘 JVM 优化&#xff1a;六道面试题与行业巨头实战解析&#xff08;1&#xff09;&#xff08;New&#xff09; 开源架构与人工智能的融合&#xff1a;开启技术新纪元&#xff08;New&#xff09; 开源架构的自动化测试策略优…

存储引擎 / 事务 / 索引

1. 存储引擎 MySQL 中特有的术语。 &#xff08;Oracle 有&#xff0c;但不叫这个名字&#xff09; 是一种表存储 / 组织数据的方式 不同的存储引擎&#xff0c;表存储数据的方式不同 1.1 查看存储引擎 命令&#xff1a; show engines \g&#xff08;或大写&#xff1a;G…

RabbitMQ运维

RabbitMQ运维 一.集群1.简单介绍2.集群的作用 二.搭建集群1.多机多节点搭建步骤 2.单机单节点搭建步骤 3.宕机演示 三.仲裁队列1.简单介绍2.Raft协议Raft基本概念主节点选举选举过程 3.仲裁队列的使用 四.HAProxy负载均衡1.安装HAProxy2.HAProxy的使用 一.集群 1.简单介绍 Ra…

Ansible 实战:Roles,运维的 “魔法函数”

一、介绍 你现在已经学过tasks和handlers&#xff0c;那么&#xff0c;最好的playbook组织方式是什么呢&#xff1f;答案很简单&#xff1a;使用roles&#xff01;roles基于一种已知的文件结构&#xff0c;能够自动加载特定的vars_files、tasks以及handlers。通过roles对内容进…

关于JVM和OS中的指令重排以及JIT优化

关于JVM和OS中的指令重排以及JIT优化 前言&#xff1a; 这东西应该很重要才对&#xff0c;可是大多数博客都是以讹传讹&#xff0c;全是错误&#xff0c;尤其是JVM会对字节码进行重排都出来了&#xff0c;明明自己测一测就出来的东西&#xff0c;写出来误人子弟… 研究了两天&…

在CPU服务器上部署Ollama和Dify的过程记录

在本指南中&#xff0c;我将详细介绍如何在CPU服务器上安装和配置Ollama模型服务和Dify平台&#xff0c;以及如何利用Docker实现这些服务的高效部署和迁移。本文分为三大部分&#xff1a;Ollama部署、Dify环境配置和Docker环境管理&#xff0c;适合需要在本地或私有环境中运行A…

【计网】TCP 协议详解 与 常见面试题

三次握手、四次挥手的常见面试题 不用死记&#xff0c;只需要清楚三次握手&#xff0c;四次挥手的流程&#xff0c;回答的时候心里要记住&#xff0c;假设网络是不可靠的 问题(1)&#xff1a;为什么关闭连接时需要四次挥手&#xff0c;而建立连接却只要三次握手&#xff1f; 关…

7.4 SVD 的几何背景

一、SVD 的几何解释 SVD 将矩阵分解成三个矩阵的乘积&#xff1a; ( 正交矩阵 ) ( 对角矩阵 ) ( 正交矩阵 ) (\pmb{正交矩阵})\times(\pmb{对角矩阵})(\pmb{正交矩阵}) (正交矩阵)(对角矩阵)(正交矩阵)&#xff0c;用几何语言表述其几何背景&#xff1a; ( 旋转 ) ( 伸缩 )…

C++的多态-上

目录 多态的概念 多态的定义及实现 1.虚函数 2. 多态的实现 2.1.多态构成条件 2.2.虚函数重写的两个例外 (1)协变(基类与派生类虚函数返回值类型不同) (2)析构函数的重写(基类与派生类析构函数的名字不同) 2.3.多态的实现 2.4.多态在析构函数中的应用 2.5.多态构成条…

内存与显存:从同根生到殊途异路的科技演进

在现代计算机的世界里&#xff0c;内存和显存是两个不可或缺的硬件组件。它们看似功能相近&#xff0c;却在发展历程中逐渐分道扬镳&#xff0c;各自服务于不同的计算需求。今天&#xff0c;我们将从一根内存条和一块显卡入手&#xff0c;深入探讨内存与显存的异同&#xff0c;…