写给初中级前端开发的技术手札(JS篇):JS概述

大家好,我是Ysh,谨以此系列文章献给正在初中级阶段的开发兄弟们,愿大家年年高升无寒冬。

创作不易,还请兄弟们多多点赞、收藏、关注 三联走起~

前言

任何高级语言的核心,通常由语法操作符数据类型流程控制语句内置功能保留字``关键字、这七项构成,我们通常是在掌握了这些语言核心项的基础上进行需求开发(构建解决方案),大部分的框架也都是根据语言的这几项进行的功能封装,因此,了解并掌握这些核心项是至关重要的。

本篇文章将对这七项语言核心进行阐明,使大家有一个基本概念。

ECMAScript:JS的核心

JavaScriptBrendan Eich 在网景公司任职,因当时需求于1995年5月开发,最初,这种语言被称为Mocha,然后改名为LiveScript,最终在与Sun Microsystems合作后命名为JavaScript(蹭Java热度)。

image.png

JavaScript一经推出火爆互联网界,但由于没有统一的规范制定,在未来两年发展中(1995~1997),JavaScript在多个浏览器中的实现存在差异,导致了兼容性问题。

为了规范和标准化JavaScript,网景公司将JavaScript提交给欧洲计算机制造商协会(ECMA)。1997年,ECMA发布了ECMAScript标准的第一版(ECMA-262)。

注意:ECMAScript是一种语言规范,任何语言都可以根据该规范实现,JavaScript实现了ECMAScript语法规范,但JS除了ECMAScript规范中定义的之外还有其他功能:DOM、BOM,如图所示:

image.png

语法

JavaScript的语法很大程度上借鉴了C语言的语法,但相对更宽松。

严格区分大小写

JavaScript是严格区分大小写的,例如:变量A与变量a 他们在JS中是两个变量。

标识符

标识符其实就是变量、函数、函数参数、对象的名称,JS定义标识符的规范如下:

  • 标识符必须为字母、下划线()或美元符号(),不能用数字开头

  • 标识符推荐使用小驼峰命名法命名,如:myName、myAge等

  • 关键字、保留字、true、false与null不能用作标识符

关键字:指的是语言中已经使用的名字,如:Object,function,基本类型Boolean的true、false 保留字:指的是语言中没有使用,但以后可能使用的名字。

注释

JavaScript采用C语言风格的注释写法,分为单行注释与多行注释:

//这是单行注释,注释了这一行的内容

/* 这是多行注释
 * 又叫块注释
 * 顾名思义会注释被引号星包含起来的一整块地方
 */

语句

JavaScript中的语句,分为单行语句与多行语句

//如声明一个变量a,单行语句应当以分号结尾
let a = 12;

//多行语句可以合并用{}合并在一起,这种合并到一起的代码又叫代码块
{
console.log(123);//在浏览器上打印123
console.log(123);//在浏览器上打印123
}

变量

在JavaScript中,变量是用于存储数据的容器,理解变量的 声明作用域提升 以及 不同类型的变量 是掌握JavaScript语法的关键点

之前我们提到过,JS的语法是宽松的,这一点在变量上有所体现,也就是说,JS的变量可以保存任何类型的数据。JS中有三个关键字用来声明变量,分别为varletconst

image.png

image.png

var name = ‘张三’; //es5声明变量关键字

let age = 21; // es6新增变量关键字

const sex = '男'; // es6新增常量关键字,声明并赋值后不可更改

var关键字

var是ES5及之前版本中用于声明变量的关键字。var声明的变量具有函数作用域或全局作用域,并且变量声明会被提升(hoisting)到作用域的顶部。

注意: 在代码块中生命的变量只会在代码块中生效,且随着代码块执行完成后销毁内存空间占用而消失,在代码块外面调用会报错:Uncaught ReferenceError

var x = 10;
console.log(x); // 10

function test() {
    var y = 20;
    console.log(y); // 20
}
test();
// console.log(y); // Uncaught ReferenceError: y is not defined
变量提升(Hoisting)

var声明的变量会被提升到其作用域的顶部,只声明没复制时会有默认值undefined,但初始化赋值不会被提升。

console.log(a); // undefined
var a = 5;
console.log(a); // 5

上述代码等价于:

var a;
console.log(a); // undefined
a = 5;
console.log(a); // 5

let

let是ES6引入的关键字,用于声明块作用域(block scope)变量。let声明的变量不会被提升。

注意: 在let声明中,同样是在代码块中生命的变量只会在代码块中生效,且随着代码块执行完成后销毁内存空间占用而消失,在代码块外面调用会报错:Uncaught ReferenceError

let x = 10;
console.log(x); // 10

{
    let y = 20;
    console.log(y); // 20
}
// console.log(y); // Uncaught ReferenceError: y is not defined
重复声明

在同一作用域中,使用let声明的变量不能重复声明。

let z = 30;
// let z = 40; // Uncaught SyntaxError: Identifier 'z' has already been declared

const关键字

const也是ES6引入的关键字,用于声明常量。常量是块作用域变量,声明时必须初始化,且值不能重新赋值。

const x = 10;
console.log(x); // 10

// x = 20; // Uncaught TypeError: Assignment to constant variable
对象和数组的常量

const声明的对象和数组的引用不能改变,但其内容是可变的。

const obj = { name: "Alice" };
obj.name = "Bob";
console.log(obj.name); // "Bob"

const arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1, 2, 3, 4]

变量作用域

变量的作用域决定了变量在何处可访问。在JavaScript中,变量作用域分为全局作用域、函数作用域和块作用域。

全局作用域

在全局作用域中声明的变量可以在代码的任何地方访问。全局变量可以通过window对象(在浏览器中)或global对象(在Node.js中)访问。

var globalVar = "I am global";

function test() {
    console.log(globalVar); // "I am global"
}
test();

函数作用域

函数作用域中的变量只能在该函数内部访问。var声明的变量具有函数作用域。

function test() {
    var functionVar = "I am inside a function";
    console.log(functionVar); // "I am inside a function"
}
test();
// console.log(functionVar); // Uncaught ReferenceError: functionVar is not defined

块作用域

块作用域是由一对花括号({})定义的。letconst声明的变量具有块作用域。

{
    let blockVar = "I am inside a block";
    console.log(blockVar); // "I am inside a block"
}
// console.log(blockVar); // Uncaught ReferenceError: blockVar is not defined

变量提升(Hoisting)

变量提升是指在代码执行前,变量声明会被提升到其作用域的顶部,但初始化不会被提升。var声明的变量会被提升,而letconst声明的变量不会被提升。

console.log(a); // undefined
var a = 5;
console.log(a); // 5

// console.log(b); // Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 10;

变量的生命周期

变量的生命周期指的是变量从声明到销毁的过程。

var 变量的生命周期

  • 声明:当进入其作用域时。

  • 初始化:当代码执行到变量声明时。

  • 销毁:当作用域结束时。

letconst 变量的生命周期

  • 声明:当进入其块作用域时。

  • 初始化:当代码执行到变量声明时。

  • 销毁:当块作用域结束时。

数据类型

JavaScript作为一种动态语言,支持多种数据类型。这些数据类型分为基本数据类型(原始类型)和复杂数据类型(引用类型),如下图所示:

image.png

image.png

基本数据类型(Primitive Types)

JavaScript的基本数据类型在当前版本下是固定不变的,这些类型包括:

1. Number

Number类型表示数字,包括整数和浮点数。JavaScript使用IEEE 754双精度64位浮点数格式来表示数字。

let integer = 42; // 整数
let float = 3.14; // 浮点数

Number类型也包含一些特殊值:

  • Infinity:表示无穷大。

  • -Infinity:表示负无穷大。

  • NaN(Not-a-Number):表示非数字值,通常是非法数学操作的结果。

console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log("hello" / 2); // NaN
2. String

String类型表示文本数据。字符串是不可变的,可以使用单引号、双引号或反引号(模板字符串)定义。

let singleQuote = 'Hello, world!';
let doubleQuote = "Hello, world!";
let templateLiteral = `Hello, ${name}!`; // 模板字符串支持插值和多行字符串
3. Boolean

Boolean类型表示布尔值,只有两个取值:truefalse

let isTrue = true;
let isFalse = false;
4. Undefined

Undefined类型表示未定义的值。当声明一个变量但未赋值时,该变量的值为undefined

let x;
console.log(x); // undefined
5. Null

Null类型表示空值,即不存在的引用。与undefined不同,null是一个表示“空”或“无”的明确值。

let y = null;
console.log(y); // null
6. Symbol

Symbol类型是ES6引入的一种新的基本数据类型,表示唯一且不可变的值。它通常用于对象属性的唯一标识符。

let symbol1 = Symbol('description');
let symbol2 = Symbol('description');
console.log(symbol1 === symbol2); // false
7. BigInt

BigInt类型也是ES6引入的一种新的基本数据类型,用于表示任意精度的整数。它通过在整数后添加n来创建。

let bigInt = 1234567890123456789012345678901234567890n;

复杂数据类型(Reference Types)

复杂数据类型是可以扩展的对象类型,值是可变的。主要包括:

1. Object

Object类型是JavaScript中最重要的复杂数据类型。对象是键值对的集合,键是字符串(也可以是Symbol),值可以是任何类型。

let person = {
    name: "John",
    age: 30,
    greet: function() {
        console.log("Hello!");
    }
};
2. Array

Array类型是用于存储有序数据集合的特殊对象。数组的元素可以是任何类型,数组长度是动态变化的。

let array = [1, 2, 3, "four", { name: "five" }];
console.log(array[0]); // 1
console.log(array[3]); // "four"
3. Function

Function类型是JavaScript中的一等公民,即函数是对象,可以赋值给变量、作为参数传递给其他函数或从其他函数返回。

function greet(name) {
    return `Hello, ${name}!`;
}
let sayHello = greet;
console.log(sayHello("Alice")); // "Hello, Alice!"
4. Date

Date类型用于处理日期和时间。JavaScript使用Date对象提供日期和时间的相关操作。

let now = new Date();
console.log(now); // 当前日期和时间
5. RegExp

RegExp类型用于表示正则表达式,提供字符串模式匹配功能。

let pattern = /hello/;
console.log(pattern.test("hello world")); // true
6. MapSet

Map类型是键值对的集合,键和值可以是任何类型。Set类型是值的集合,所有值都是唯一的。

let map = new Map();
map.set("key", "value");
console.log(map.get("key")); // "value"

let set = new Set();
set.add(1);
set.add(2);
set.add(2); // 重复值不会添加
console.log(set.size); // 2
7. WeakMapWeakSet

WeakMapWeakSet类似于MapSet,但其键和值是弱引用,可以被垃圾回收机制回收,不会阻止对象被回收。

let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "value");
console.log(weakMap.get(obj)); // "value"

动态类型与类型转换

JavaScript是动态类型语言,变量的类型可以在运行时改变。类型转换分为显式转换和隐式转换。

显式转换

显式转换是通过使用内置函数或运算符进行的。

let num = "123";
let number = Number(num); // 字符串转换为数字
let str = String(number); // 数字转换为字符串
let bool = Boolean(number); // 非零数字转换为布尔值true
隐式转换

隐式转换是JavaScript在运行时自动进行的类型转换。

let result = "5" - 3; // 2,字符串"5"被隐式转换为数字
let concat = "5" + 3; // "53",数字3被隐式转换为字符串

操作符

在JavaScript中,操作符是JavaScript中执行各种操作的基本单位,是对值进行操作的符号或关键字,且可以对一个或多个值进行操作,并返回结果。

基本算术操作符

加法操作符(+

用于两个数值相加或连接两个字符串。

let sum = 5 + 3; // 8
let concatenatedString = "Hello, " + "world!"; // "Hello, world!"
减法操作符(-

用于两个数值相减。

let difference = 10 - 4; // 6
乘法操作符(*

用于两个数值相乘。

let product = 6 * 7; // 42
除法操作符(/

用于两个数值相除。

let quotient = 20 / 4; // 5
取模操作符(%

用于计算两个数值相除的余数。

let remainder = 10 % 3; // 1
指数操作符(**

用于计算第一个操作数的第二个操作数次幂。

let power = 2 ** 3; // 8

赋值操作符

简单赋值操作符(=

将右侧的值赋给左侧的变量。

let x = 10;
复合赋值操作符

用于将算术操作和赋值操作结合。

let y = 5;
y += 3; // 等价于 y = y + 3; 结果是 8
y -= 2; // 等价于 y = y - 2; 结果是 6
y *= 4; // 等价于 y = y * 4; 结果是 24
y /= 3; // 等价于 y = y / 3; 结果是 8
y %= 5; // 等价于 y = y % 5; 结果是 3
y **= 2; // 等价于 y = y ** 2; 结果是 9

比较操作符

相等操作符(==

比较两个值是否相等,进行类型转换。

console.log(5 == "5"); // true
全等操作符(===

比较两个值是否全等,不进行类型转换。

console.log(5 === "5"); // false
不相等操作符(!=

比较两个值是否不相等,进行类型转换。

console.log(5 != "5"); // false

不全等操作符(!==

比较两个值是否不全等,不进行类型转换。

console.log(5 !== "5"); // true
大于操作符(>

比较左侧值是否大于右侧值。

console.log(10 > 5); // true
大于或等于操作符(>=

比较左侧值是否大于或等于右侧值。

console.log(10 >= 10); // true
小于操作符(<

比较左侧值是否小于右侧值。

console.log(5 < 10); // true
小于或等于操作符(<=

比较左侧值是否小于或等于右侧值。

console.log(10 <= 10); // true

逻辑操作符

逻辑与操作符(&&

用于两个操作数都为真时,返回真,否则返回假。

console.log(true && false); // false
console.log(true && true); // true
逻辑或操作符(||

用于两个操作数中至少有一个为真时,返回真,否则返回假。

console.log(true || false); // true
console.log(false || false); // false
逻辑非操作符(!

用于取反操作数的布尔值。

console.log(!true); // false
console.log(!false); // true

位操作符

位操作符对其操作数的二进制表示形式进行操作。

按位与操作符(&

对两个数值的每一位执行与(AND)操作。

console.log(5 & 1); // 1 (0101 & 0001 = 0001)
按位或操作符(|

对两个数值的每一位执行或(OR)操作。

console.log(5 | 1); // 5 (0101 | 0001 = 0101)
按位异或操作符(^

对两个数值的每一位执行异或(XOR)操作。

console.log(5 ^ 1); // 4 (0101 ^ 0001 = 0100)
按位非操作符(~

对数值的每一位执行非(NOT)操作。

console.log(~5); // -6 (~0101 = 1010)
左移操作符(<<

将一个数值的所有位向左移动指定的位数。

console.log(5 << 1); // 10 (0101 << 1 = 1010)
右移操作符(>>

将一个数值的所有位向右移动指定的位数。

console.log(5 >> 1); // 2 (0101 >> 1 = 0010)
无符号右移操作符(>>>

将一个数值的所有位向右移动指定的位数,并用零填充左侧的位。

console.log(5 >>> 1); // 2 (0101 >>> 1 = 0010)

其他操作符

三元操作符(? :

根据条件表达式的值来返回一个值。

let age = 20;
let allowed = (age >= 18) ? "Yes" : "No";
console.log(allowed); // "Yes"
逗号操作符(,

在一行代码中执行多个操作,并返回最后一个操作的结果。

let x = (1 + 2, 3 + 4);
console.log(x); // 7
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 function(){}); // "function"
delete 操作符

用于删除对象的属性。

let obj = { name: "Alice", age: 25 };
delete obj.age;
console.log(obj); // { name: "Alice" }
in 操作符

用于检查对象是否包含特定的属性。

let obj = { name: "Alice", age: 25 };
console.log("name" in obj); // true
console.log("gender" in obj); // false
instanceof 操作符

用于检查对象是否是某个构造函数的实例。

let arr = [];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true

语句

在JavaScript中,语句是构成程序的基本单位。每个语句执行特定的操作,并以分号(;)结束。

变量声明语句

var 语句

用于声明一个变量。

var x = 10;
let 语句

用于声明一个块作用域的变量。

let y = 20;
const 语句

用于声明一个块作用域的常量。

const z = 30;

表达式语句

表达式语句是以表达式开头的语句。它们通常用于赋值、调用函数或执行算术运算。

x = y + z;
console.log(x);

条件语句

条件语句根据表达式的值来执行不同的代码块。

if 语句

根据条件表达式的值执行代码块。

if (x > 10) {
    console.log("x is greater than 10");
}
if...else 语句

根据条件表达式的值执行不同的代码块。

if (x > 10) {
    console.log("x is greater than 10");
} else {
    console.log("x is less than or equal to 10");
}
if...else if...else 语句

检查多个条件。

if (x > 10) {
    console.log("x is greater than 10");
} else if (x < 5) {
    console.log("x is less than 5");
} else {
    console.log("x is between 5 and 10");
}
switch 语句

根据表达式的值执行多个代码块中的一个。

switch (x) {
    case 1:
        console.log("x is 1");
        break;
    case 2:
        console.log("x is 2");
        break;
    default:
        console.log("x is neither 1 nor 2");
}

循环语句

循环语句用于重复执行代码块。

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 语句

用于遍历对象的可枚举属性。

let obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
    console.log(key, obj[key]);
}
for...of 语句

用于遍历可迭代对象(如数组、字符串、Map和Set)。

let arr = [1, 2, 3];
for (let value of arr) {
    console.log(value);
}

跳转语句

跳转语句用于改变代码的执行顺序。

break 语句

终止当前循环或代码块,并跳出该循环或代码块。

for (let i = 0; i < 5; i++) {
    if (i === 3) {
        break;
    }
    console.log(i);
}
continue 语句

终止当前循环的当前迭代,并继续执行下一个迭代。

for (let i = 0; i < 5; i++) {
    if (i === 3) {
        continue;
    }
    console.log(i);
}
return 语句

终止当前函数的执行,并返回一个值。

function sum(a, b) {
    return a + b;
}
console.log(sum(2, 3)); // 5
throw 语句

抛出一个用户自定义的异常。

function checkAge(age) {
    if (age < 18) {
        throw new Error("You must be at least 18 years old.");
    }
    return "Access granted";
}
try...catch 语句

用于处理异常。try块包含可能抛出异常的代码,catch块包含处理异常的代码。

try {
    let result = checkAge(16);
    console.log(result);
} catch (error) {
    console.log(error.message);
}

其他语句

debugger 语句

用于停止代码执行,并调用调试工具,使用调试工具手动执行后续代码。

function debugExample() {
    debugger;
    console.log("Debugging");
}
debugExample();
with 语句 (已弃用)

用于将代码的作用域设置为特定的对象(不推荐使用,因为可能导致代码难以理解和调试)。

let obj = { a: 1, b: 2 };
with (obj) {
    console.log(a); // 1
    console.log(b); // 2
}

空语句

空语句用于创建没有任何执行语句的代码块。

for (let i = 0; i < 5; i++) {
    ; // 空语句
}

标签语句

标签语句用于标识代码块,以便与breakcontinue语句一起使用。

outerLoop: for (let i = 0; i < 5; i++) {
    for (let j = 0; j < 5; j++) {
        if (j === 3) {
            break outerLoop;
        }
        console.log(i, j);
    }
}

函数

函数是JavaScript中强大的编程工具,将可重复使用的代码块进行封装,函数不仅可以执行特定任务,还可以返回值。

函数声明

函数声明使用function关键字,并且有一个可选的名称。

function greet(name) {
    return `Hello, ${name}!`;
}

函数可以通过名称调用,并传递参数:

let message = greet("Alice");
console.log(message); // "Hello, Alice!"

函数表达式

函数表达式是将函数赋值给变量或常量。函数表达式可以是匿名的,也可以是命名的。

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

// 命名函数表达式
let greet = function greetFunction(name) {
    return `Hello, ${name}!`;
};
箭头函数

箭头函数是ES6引入的一种简洁的函数表达方式(语法糖),它使用=>语法,使其语法更简短,但没有自己的this指向。

let greet = (name) => {
    return `Hello, ${name}!`;
};

// 如果函数体只有一个表达式,可以省略花括号和`return`关键字
let greet = (name) => `Hello, ${name}!`;
函数参数

函数可以接受参数,也可以有默认参数值。

function greet(name = "Guest") {
    return `Hello, ${name}!`;
}

console.log(greet()); // "Hello, Guest!"
console.log(greet("Alice")); // "Hello, Alice!"
Rest参数

Rest参数允许函数接受不定数量的参数,并将它们作为数组传入。

function sum(...numbers) {
    return numbers.reduce((total, number) => total + number, 0);
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(4, 5)); // 9
Arguments对象

在非箭头函数中,arguments对象会包含传递给函数的所有参数。它类似数组,但不是数组实例。

function sum() {
    let total = 0;
    for (let i = 0; i < arguments.length; i++) {
        total += arguments[i];
    }
    return total;
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(4, 5)); // 9

函数返回值

函数可以返回值,使用return语句。如果没有return语句,函数会返回undefined

function multiply(a, b) {
    return a * b;
}

console.log(multiply(2, 3)); // 6

function noReturn() {
    let x = 10;
}

console.log(noReturn()); // undefined

函数作用域和闭包

作用域

函数作用域指的是变量在函数内的可见性。在函数内部声明的变量在函数外部不可见。

function test() {
    let x = 10;
    console.log(x); // 10
}
test();
// console.log(x); // Uncaught ReferenceError: x is not defined
闭包

闭包是指函数可以访问其词法作用域中的变量,即使函数在其词法作用域之外执行。

function outer() {
    let outerVar = "I'm outside!";
    
    function inner() {
        console.log(outerVar); // "I'm outside!"
    }
    
    return inner;
}

let innerFunc = outer();
innerFunc();

高阶函数

高阶函数是指可以接受一个或多个函数作为参数,或返回一个函数作为结果的函数。

接受函数作为参数
function applyOperation(a, b, operation) {
    return operation(a, b);
}

function add(x, y) {
    return x + y;
}

function multiply(x, y) {
    return x * y;
}

console.log(applyOperation(5, 3, add)); // 8
console.log(applyOperation(5, 3, multiply)); // 15
返回一个函数
function createGreeting(greeting) {
    return function(name) {
        return `${greeting}, ${name}!`;
    };
}

let sayHello = createGreeting("Hello");
let sayHi = createGreeting("Hi");

console.log(sayHello("Alice")); // "Hello, Alice!"
console.log(sayHi("Bob")); // "Hi, Bob!"

自调用函数(IIFE)

自调用函数(Immediately Invoked Function Expression,IIFE)是一种定义后立即执行的函数。

(function() {
    console.log("This is an IIFE");
})();

函数递归

递归是函数调用自身的技术。它用于解决需要重复分解问题的场景。

function factorial(n) {
    if (n === 0) {
        return 1;
    }
    return n * factorial(n - 1);
}

console.log(factorial(5)); // 120

函数作为对象的方法

函数可以作为对象的方法,this关键字在方法中指向调用该方法的对象。

let person = {
    name: "Alice",
    greet: function() {
        return `Hello, ${this.name}!`;
    }
};

console.log(person.greet()); // "Hello, Alice!"

异步函数

回调函数

回调函数是作为参数传递给另一个函数,并在特定事件发生时调用的函数。

function fetchData(callback) {
    setTimeout(() => {
        let data = "Data fetched";
        callback(data);
    }, 1000);
}

fetchData(function(data) {
    console.log(data); // "Data fetched"
});
Promise

Promise是ES6引入的用于处理异步操作的对象。

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("Data fetched");
    }, 1000);
});

promise.then(data => {
    console.log(data); // "Data fetched"
}).catch(error => {
    console.error(error);
});
Async/Await

Async/Await是ES8引入的用于处理Promise的语法糖,使异步代码看起来像同步代码。

async function fetchData() {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("Data fetched");
        }, 1000);
    });
    
    let data = await promise;
    console.log(data); // "Data fetched"
}

fetchData();

关键字

关键字是JavaScript中具有预定义功能的词汇,它们用于执行特定操作或定义语言结构。以下是JavaScript中的关键字及其作用:

控制结构关键字

  • if:用于条件语句。

  • else:用于条件语句的替代分支。

  • switch:用于多分支条件语句。

  • case:用于定义switch语句中的一个分支。

  • default:用于定义switch语句中的默认分支。

循环关键字

  • for:用于循环。

  • while:用于循环。

  • do:用于do...while循环。

  • break:用于跳出循环或switch语句。

  • continue:用于跳过循环的当前迭代。

函数关键字

  • function:用于定义函数。

  • return:用于从函数中返回值。

变量声明关键字

  • var:用于声明变量(具有函数作用域)。

  • let:用于声明块作用域变量(ES6引入)。

  • const:用于声明块作用域常量(ES6引入)。

作用域和上下文关键字

  • this:用于引用当前对象。

  • new:用于创建对象的实例。

  • delete:用于删除对象的属性。

  • typeof:用于确定变量的数据类型。

  • instanceof:用于测试对象是否为某构造函数的实例。

  • in:用于判断属性是否在对象中。

异常处理关键字

  • try:用于定义一个可能抛出异常的代码块。

  • catch:用于捕获并处理异常。

  • finally:用于定义一个总会执行的代码块(不论是否抛出异常)。

  • throw:用于抛出一个用户自定义的异常。

类与模块关键字(ES6引入)

  • class:用于定义类。

  • extends:用于继承类。

  • super:用于调用父类的构造函数或方法。

  • import:用于导入模块。

  • export:用于导出模块。

其他关键字

  • void:用于指定表达式不返回值。

  • yield:用于生成器函数。

  • await:用于异步函数。

  • async:用于定义异步函数。

保留字

保留字是被JavaScript语言保留,但当前未作为关键字使用的词汇。这些词汇在未来版本中可能会被用作关键字,因此不能用作标识符。以下是JavaScript中的保留字:

未来保留字(包括严格模式下)

  • enum:用于定义枚举(未来可能引入)。

  • implements:用于接口实现(未来可能引入)。

  • interface:用于定义接口(未来可能引入)。

  • package:用于定义包(未来可能引入)。

  • private:用于定义私有属性或方法(未来可能引入)。

  • protected:用于定义受保护的属性或方法(未来可能引入)。

  • public:用于定义公共属性或方法(未来可能引入)。

  • static:用于定义静态属性或方法(未来可能引入)。

其他保留字

这些词汇虽然目前不是关键字,但在严格模式(strict mode)下也不能作为标识符使用:

  • await

  • yield

已弃用或仅在特定环境中保留

某些保留字在早期版本中使用,但在现代JavaScript中已经弃用或仅在特定环境下保留:

  • abstract

  • boolean

  • byte

  • char

  • double

  • final

  • float

  • goto

  • int

  • long

  • native

  • short

  • synchronized

  • transient

  • volatile

总结

前言

任何高级语言的核心通常由以下七项构成:语法操作符数据类型流程控制语句内置功能保留字关键字。我们通常是在掌握这些语言核心项的基础上进行需求开发(构建解决方案)。大部分框架也基于这些核心项进行功能封装,因此,了解并掌握这些核心项是至关重要的。本篇文章将对这七项语言核心进行阐明,使大家有一个基本概念。

ECMAScript:JS的核心

JavaScript由Brendan Eich在网景公司开发,最初称为Mocha,后改名为LiveScript,最终在与Sun Microsystems合作后命名为JavaScript。由于缺乏统一规范,JavaScript在早期发展中出现了兼容性问题。为了解决这个问题,网景公司将JavaScript提交给欧洲计算机制造商协会(ECMA),1997年发布了ECMAScript标准第一版(ECMA-262)。

语法

JavaScript的语法借鉴了C语言,但相对更宽松。其主要特点包括:

  • 严格区分大小写:如变量A和变量a是不同的。

  • 标识符:必须以字母、下划线或美元符号开头,不能用数字开头,推荐使用小驼峰命名法。

  • 注释:单行注释用//,多行注释用/* ... */

  • 语句:以分号结束,多行语句可以用{}包裹。

变量

JavaScript的变量可以保存任何类型的数据,有三个关键字用于声明变量:varletconst

  • var:函数作用域或全局作用域,声明会被提升。

  • let:块作用域,不会被提升,不能重复声明。

  • const:块作用域,声明时必须初始化,且值不能重新赋值。对象和数组的引用不能改变,但内容是可变的。

数据类型

JavaScript支持基本数据类型(原始类型)和复杂数据类型(引用类型)。

  • 基本数据类型NumberStringBooleanUndefinedNullSymbolBigInt

  • 复杂数据类型ObjectArrayFunctionDateRegExpMapSetWeakMapWeakSet

操作符

JavaScript中的操作符用于对值进行操作,包括基本算术操作符、赋值操作符、比较操作符、逻辑操作符、位操作符和其他操作符。

  • 算术操作符+-*/%**

  • 赋值操作符=+=-=*=/=%=**=

  • 比较操作符=====!=!==>>=<<=

  • 逻辑操作符&&||!

  • 位操作符&|^~<<>>>>>

  • 其他操作符?:,typeofdeleteininstanceof

语句

JavaScript中的语句是构成程序的基本单位,包括:

  • 变量声明语句varletconst

  • 表达式语句:赋值、调用函数或执行算术运算。

  • 条件语句ifelseswitchcasedefault

  • 循环语句forwhiledo...whilefor...infor...of

  • 跳转语句breakcontinuereturnthrowtry...catch

  • 其他语句debuggerwith(已弃用)、空语句、标签语句。

函数

函数是JavaScript中强大的编程工具,用于封装可重用的代码块。包括:

  • 函数声明:使用function关键字。

  • 函数表达式:将函数赋值给变量或常量。

  • 箭头函数:使用=>语法。

  • 函数参数:支持默认参数值、Rest参数和arguments对象。

  • 函数返回值:使用return语句。

  • 函数作用域和闭包:函数内的变量在函数外不可见,闭包可以访问其词法作用域中的变量。

  • 高阶函数:接受一个或多个函数作为参数,或返回一个函数。

  • 自调用函数(IIFE):定义后立即执行的函数。

  • 函数递归:函数调用自身。

  • 函数作为对象的方法this关键字指向调用该方法的对象。

  • 异步函数:回调函数、Promise和Async/Await。

关键字

关键字是JavaScript中具有预定义功能的词汇,用于执行特定操作或定义语言结构。包括:

  • 控制结构关键字ifelseswitchcasedefault

  • 循环关键字forwhiledobreakcontinue

  • 函数关键字functionreturn

  • 变量声明关键字varletconst

  • 作用域和上下文关键字thisnewdeletetypeofinstanceofin

  • 异常处理关键字trycatchfinallythrow

  • 类与模块关键字classextendssuperimportexport

  • 其他关键字voidyieldawaitasync

保留字

保留字是被JavaScript语言保留,但当前未作为关键字使用的词汇。这些词汇在未来版本中可能会被用作关键字,因此不能用作标识符。包括:

  • 未来保留字enumimplementsinterfacepackageprivateprotectedpublicstatic

  • 其他保留字awaityield

  • 已弃用或仅在特定环境中保留abstractbooleanbytechardoublefinalfloatgotointlongnativeshortsynchronizedtransientvolatile

通过对这些JavaScript核心概念的掌握,可以为日后的高级开发和框架学习打下坚实的基础。希望这篇文章能帮助大家更好地理解和应用JavaScript,愿大家年年高升,无寒冬!

  • 33
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你的问题是关于Python函数第二次运行报错和retry的简单用法。 首先,如果一个Python函数在第二次运行时出现了错误,可能是由于函数内部的变量状态发生了变化,导致程序出错。为了解决这个问题,可以使用retry功能来多次尝试运行该函数,直到它成功为止。 使用retry功能可以在函数出现错误时自动重试,可以避免动重复运行该函数,从而提高效率。 下面是一个简单的示例代码,演示了如何使用retry功能: ```python import time from retry import retry @retry(delay=1, backoff=2, max_delay=4) def my_func(): print("Running my_func...") # 模拟函数出错 if time.time() % 2 == 0: raise ValueError("Oops! Something went wrong...") else: print("Success!") my_func() ``` 在这个示例代码中,我们使用了retry库中的retry装饰器来装饰my_func函数,该函数会运行多次,直到成功为止。在retry装饰器中,我们设置了最大延迟时间为4秒,每次重试前等待1秒,重试间隔时间呈指数级增长,即第一次重试后等待1秒,第二次重试后等待2秒,第三次重试后等待4秒,以此类推,直到达到最大延迟时间为止。 当my_func函数第一次运行时,它会输出“Running my_func...”和“Success!”,并正常结束。当函数第二次运行时,它会抛出一个ValueError异常,并重试多次,直到成功为止。 希望这个简单的示例可以帮助你理解如何使用retry功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值