JavaScript复习-面试《持续更新》

一、数据类型

JS有两种数据类型,分别为基本数据类型引用数据类型

1.1 基本数据类型:

1. number:数字,包含整数和浮点数。如:10,3.14
2. string:字符串,用单引号或双引号包裹的文本。如:'123',"世界"
3. boolean:布尔值,true | false
4. null:空值,表示空值或不存在的对象。
5. undefined:未定义,表示声明了变量但未赋初值。
6. (es6新增)bigInt:用于表示任意精度的整数。
7. (es6新增)symbol:符号,表示唯一标识符,用`Symbol()`创建。如:const symbol = Symbol("symbol")

1.2 引用数据类型:

1. Object:对象
2. Function:函数
3. Array:数组
4. Date:日期

二、数据之间的计算

2.1 算术运算

运算方式符号
加/减/乘/除+ - * /
递增++
递减- -
取模(取余数)%
**

例子:

// 递增:**
var b = 10;
c = b++ + ++b; // b++ = 10, ++b=12
console.log(c); // 22

// 取模(取余数):%
var c = 7 % 3;
console.log(c); // 1

// 幂运算: **
var d = 2 ** 3;
console.log(d); // 8

2.2 逻辑运算

运算方式符号例子
逻辑与&&true && false 结果为 false
逻辑或||true
逻辑非!!true 结果为 false

逻辑与:一假全假
逻辑或:一真全真

逻辑中断语法返回值
逻辑与短路运算表达式1 && 表达式2如果表达式1为真,则返回表达式2;如果表达式1为假,则返回表达式1;
逻辑或短路运算表达式1 || 表达式2如果表达式1为真,则返回表达式1;如果表达式1为假,则返回表达式2;

2.3 比较运算

运算方式符号
大于、小于><
大于等于、小于等于>=<=
等于=====
不等于!=!==

注意:
1.浮点数之间尽量避免直接运算,因为可能会造成精度问题。
2.不要直接判断两个浮点数是否相等。
例子:

const num1 = 5/3 + 6/3;
const num2 = 11/3;
console.log(num1 ==num2); // false

2.4 赋值运算符

运算方式符号
等于=
加/减/乘/除等于+=-=*=/=
模等于%=

三、数据之间的转换

3.1 数字与字符串之间的转换

  • 字符串转换为数字
    • 显式转换:

      // parseInt:自动取整
      const str = 3.14;
      const num = parseInt(str);
      console.log(num);  // 3
      
      // parseFloat
      const str = 3.14;
      const num = parseFloat(str);
      console.log(num);  // 3.14
      
      // Number()
      const str = 3.14;
      const num = Number(str);
      console.log(num);  // 3.14
      
    • 隐式转换:

      // 利用算术运算:- * / 进行隐士转换
      const str = '30';
      const num1 = str - 13; // 17
      const num2 = str * 2;  // 60
      const num3 = str / 5;  // 6
      
      // 利用一元 + 号操作符,进行隐式转换
      const str = '30';
      constr num4 = +str;
      console.log(num4);  // 30
      
  • 数字转换为字符串
    • 显式转换
      // String()
      const num = 123;
      const str = String(num);
      console.log(typeof str); //  string 
      
      // toString()
      const num = 234;
      const str = num.toString();
      console.log(tyoeof str): // string
      
      // toLocalString()
      const num = 234;
      const str = num.toLocalString();
      console.log(tyoeof str): // string
      
    • 隐式转换
      // 空字符串拼接
      const num = 123;
      const str = '' + num;
      console.log(str); // '123'
      
      // 模板字符串
      const num = 456;
      const str = `${num}`;
      console.log(typeof str);  // string
      

3.2 数组与字符串之间的转换

  • 数组转换为字符串

    • join():将数组元素以指定的分隔符连接成一个字符串
      const array = [1,2,3,4,5];
      const str = array.join(','); // 可以修改
      console.log(str); // 1,2,3,4,5
      
    • toString():将数组转换为由逗号分隔的字符串
      const array = [1,2,3,4,5];
      const str = array.toString();
      console.log(str); // 1,2,3,4,5
      
    • 模板自变量:通过遍历数组元素使用字符串拼接的方式
      const array = [1,2,3,4,5];
      let str = '';
      for(var i = 0;i< array.length;i++){
      	str += array[i].toString();
      }
      console.log(str); // 12345
      

    注意: 在不确定数组中的元素是 数字类型 时,建议使用 str += array[i].toString() ,避免在使用 str += array[i] 直接拼接时出现不必要的错误和意外结果。

  • 字符串转换为数组

    • split():根据指定的分隔符将字符串分隔成数组的元
      const str = '1,2,3,4,5';
      const array = str.split(','); // 将逗号分隔的字符串转换为数组
      console.log(array); ['1', '2', '3', '4', '5']
      
    • 拓展运算符
      const str = '12345';
      const array = [...str];
      console.log(array); // ['1', '2', '3', '4', '5']
      
    • Array.from():将字符串转换为包含单个字符的数组
      const str = "Hello";
      const arr = Array.from(str);
      console.log(arr); // 输出 ["H", "e", "l", "l", "o"]
      

3.3 布尔型与其他类型之间的转换

  • 布尔型与数字类型的转换
    • 数字类型转换为布尔值:Boolean(),除了0,其他都会被转换成 true
    • 布尔值转换为数字类型:Number()true1false0
  • 布尔型与字符串类型的转换
    • 字符串类型转换为布尔值:Boolean(),除了空串"",其它都为 true
    • 布尔值转换为字符串类型:String()
  • 其他类型转换为布尔型:Boolean()
    • 对象、数组等转布尔值:全为 true
    • NaN、undefined、Null转布尔值:权为 false

3.4 对象与数组之间的转换

  • 对象转换为数组
    • array.from():将类似数组或可迭代对象转换为真正的数组。
      const arrayLike = {0: "a", 1: "b", 2: "c", length: 3};
      const array = Array.from(arrayLike);
      console.log(array); // ["a", "b", "c"]
      
    • Object.keys():获取对象的所有键,并存储在一个数组中
      const obj = { name: "John", age: 30 };
      const arr = Object.keys(obj);
      console.log(arr); // ['name', 'age']
      
    • Object.values():获取对象的所有值,并存储在一个数组中
      const obj = { name: "John", age: 30 };
      const arr = Object.values(obj);
      console.log(arr); //['John', 30]
      
    • Object.entries():将对象转换为包含键值对的数组
      const obj = { name: "John", age: 30 };
      const arr = Object.entries(obj);
      console.log(arr);  //  [["name", "John"], ["age", 30]]
      
    • 手动遍历对象
      const obj = { name: 'John', age: 30, city: 'New York' };
      const arr = [];
      for (let key in obj) {
      	if (obj.hasOwnProperty(key)) {
      	arr.push(obj[key]);
      	}
      }
      console.log(arr); // 输出 ["John", 30, "New York"]
      
  • 数组转换为对象
    • Array.reduce():需要制定一个回调函数来处理每个数组元素,并将其添加为对象的属性。
      const arr = [["name","John"],["age",30]];
      const obj =  arr.reduce((acc,[key,value]) => {
      	acc[key] = value;
      	return acc;
      },{});
      console.log(obj); // {name: 'John', age: 30}
      
    • forEach():遍历数组,并将数组中的元素转换为对象的属性和值。
      const arr = [["name","John"],["age",30]];
      const obj = {};
      arr.forEach(([key,value]) => {
      	obj[key] = value;
      })
      console.log(obj);  // {name: 'John', age: 30}
      
    • ES6中的解构赋值
      const arr = [["name","John"],["age",30]];
      const obj = Object.fromEntries(arr);
      console.log(obj); // {name: 'John', age: 30}
      
    注意:reduce()方法可以自定义转换逻辑;forEach()方法适用于简单的遍历和赋值操作;ES6对象解构可以简洁的转换数组到对象。

四、流程控制

4.1 条件语句

  • if 分支语句
  • if-else 双分支语句
  • if-else-if 多分支语句:在多个条件中进行选择执行
  • switch语句:根据表达式中的多个选项中进行条件判断,并执行匹配的代码块。
  • 三元表达式(?:):根据条件的真假返回不同的值或执行不同的表达式。
    例:
    x = x > 10 ? 10 : x  // 如果x>10,则令 x=10;否则等于其本身
    
  • 逻辑与(&&)逻辑或(||) 运算符:根据条件的真假继续执行后续代码或跳过后续代码。
    condition1 && statement; // 当条件1为真时 执行语句
    condition2 || statement; // 当条件2为假时 执行语句
    

4.2 循环语句

  • for 循环:按照指定条件重复执行代码块
    for(初始化;循环条件;迭代) {
    	// 代码块
    }
    
  • while 循环:条件为真时重复执行代码块
    while(条件) {
    	// 代码块
    }
    
  • do…while 循环:先执行一次代码块,然后在条件为真时重复执行
    do {
    	// 代码块
    } while(条件)
    
  • for…in 循环:用于遍历对象的可枚举属性
    for(variable in object) {
    	// 每个可枚举属性都会进入循环体执行相关代码
    }
    
  • for…of 循环:用于遍历可迭代对象(如数组、字符串、Set、Map等)的元素。
    for(variable of iterable) {
    	// 遍历可迭代对象的每个元素,并执行相关代码
    }
    
  • forEach循环:用于遍历数组的每个元素并执行回调函数
    array.forEach(function(element, index, array) {
    	// 在这里执行对每个元素的操作
    });
    
  • continue 和 break 关键字
    • continue:遇到则跳出本次循环语句
    • break:遇到则跳出整个循环

4.3 异常处理

  • try...catch 语句:用于捕获和处理代码块中的异常。

    try {
    	// 可能会抛出异常的代码块
    } catch (error) {
    	// 在这里处理异常
    }
    
  • throw 语句:用于手动抛出异常。

    throw expression; // expression 可以是任何表达式,通常是一个 Error 对象或其子类的实例
    
  • finally 语句:可选的 try…catch 语句的扩展部分,无论是否有异常都会执行其中的代码。

    try {
    	// 可能会抛出异常的代码块
    } catch (error) {
    	// 在这里处理异常
    } finally {
    	 // 在这里的代码无论有无异常都会执行
    }
    
  • 自定义异常:可以通过创建Error类的子类来自定义异常,并添加自定义的属性和方法。

    class MyCustomError extends Error {
    	constructor(message) {
    		super(message);
    		this.name = 'MyCustomError';
    	}
    }
    

五、数组相关方法

5.1 检测是否为数组

  • isArray:语法:Array.isArray(arr) 返回值:true/false
  • instanceof:语法: arr instanceof Array 返回值:true/false
  • constructor:语法:arr.constructor === Array 返回值:true/false

5.2 添加元素

  • push():向 数组末尾 添加一个或多个元素,并返回修改后的数组。
  • unshift():向 数组开头 添加一个或多个元素,并返回修改后的数组。

5.3 删除元素

  • pop():从 数组末尾 移除一个元素,并返回该元素的值。
  • shift():从 数组开头 移除第一个元素,并返回该元素的值。

5.4 数组合并

  • concat():将多个数组合并为一个新数组。
  • 拓展运算符:可利用拓展运算符进行数组合并。

5.5 数组截取 - - 返回新数组

  • slice():从原数组中截取指定范围的元素,返回一个新数组
    • 语法:arr.slice(startIndex, endIndex); 将索引为 startIndex 的元素到 endIndex 的元素之间的所有元素组成一个新数组。(不包含索引为endIndex元素)
    const arr = [1, 2, 3, 4, 5];
    const slicedArr = arr.slice(1, 4);
    console.log(slicedArr); // [2, 3, 4]
    console.log(arr); // [1, 2, 3, 4, 5](原数组未改变)
    
  • splice():从数组中删除、替换或添加元素,并返回被删除的元素组成的数组
    • 语法:arr.splice(startIndex, n, 插入的元素) 从索引为startIndex的元素开始,向后删除 n 个元素,并将后面的元素插入到相应位置。
    const arr = [1, 2, 3, 4, 5];
    const removedElements = arr.splice(1, 3, 'a', 'b');
    console.log(arr); // [1, 'a', 'b', 5]
    console.log(removedElements); // [2, 3, 4]
    

5.6 其它

  • map():遍历数组元素中的每个元素,并根据映射返回一个新数组
    const arr = [1, 2, 3];
    const newArr = arr.map(x => x * 2);
    console.log(newArr); // [2, 4, 6]
    
  • filter():根据指定条件筛选数组中的元素,并返回符合条件的新数组
    const arr = [1, 2, 3, 4, 5];
    const filteredArr = arr.filter(x => x % 2 === 0);
    console.log(filteredArr); // [2, 4]
    
  • reduce():将数组中元素通过指定的函数进行积累运算,并返回最终结果
    const arr = [1, 2, 3, 4, 5];
    const sum = arr.reduce((acc, curr) => acc + curr, 0);
    console.log(sum); // 15
    
  • every():检查数组中的所有元素是否满足指定条件,并返回布尔值
    const arr = [1, 2, 3, 4, 5];
    const result = arr.every(x => x > 0);
    console.log(result); // true
    
  • some():检查数组是否至少存在一个元素满足指定条件,并返回布尔值
    const arr = [1,2,3,4,5];
    const result = arr.some(x => x>2);
    console.log(result); // true
    
  • find():在数组中查找满足条件的第一给元素,并返回该元素。如果找不到符合条件的元素则返回undefined
    const array = [1, 2, 3, 4, 5];
    const evenNumber = array.find((num) => num % 2 === 0);
    console.log(evenNumber); // 输出: 2
    
  • findIndex():返回数组中满足提供的测试函数的第一个元素的索引,若未找到则返回 -1。
    const arr = [1, 2, 3, 4, 5];
    const index = arr.findIndex(x => x > 2);
    console.log(index); // 2
    
  • indexOf():返回数组中首次出现指定元素的索引。如果找不到则返回 -1
    const index = array.indexOf(element);
    
  • includes():判断数组是否包含指定元素,并返回布尔值
    const isFound = array.includes(element);
    
  • sort():对数组进行排序,默认按照字符串的 Unicode 编码进行排序。
    const arr = [1,3,4,2,5];
    arr.sort();
    console.log(arr); // [1, 2, 3, 4, 5]
    
  • reverse():反转数组中元素的顺序。
    const arr = [1,2,3,4,5];
    arr.reverse();
    console.log(arr); // [5, 4, 3, 2, 1]
    
  • from():将类似数组或可迭代对象转换为真正的数组。
    const str = 'Hello';
    const arr = Array.from(str);
    console.log(arr); // ['H', 'e', 'l', 'l', 'o']
    
    const nums = [1, 2, 3];
    const newArr = Array.from(nums, x => x * 2);
    console.log(newArr); // [2, 4, 6]
    
  • of():根据传入的参数创建一个新的数组。
    const arr = Array.of(1, 2, 3, 4);
    console.log(arr); // [1, 2, 3, 4]
    
    const emptyArr = Array.of();
    console.log(emptyArr); // []
    

六、字符串相关方法

6.1 访问方法

  • charAt(index):返回指定索引位置的字符。
  • charCodeAt(index):返回指定索引位置处的 Unicode 值。
  • cocact(str1, str2, ...):连接两个或多个字符串,并返回新字符串。
  • substring(startIndex, endIndex):提取字符串中指定起始索引至结束索引范围内的字符。(不包含endIndex)
  • slice(startIndex, endIndex):与 substring() 方法类似,提取字符串中指定起始索引至结束索引范围内的字符。(不包含endIndex)
var str = "Hello, world!";
console.log(str.charAt(0));  // 输出:H
console.log(str.charCodeAt(4));  // 输出:111
console.log(str.concat(" Welcome"));  // 输出:Hello, world! Welcome
console.log(str.substring(7, 12));  // 输出:world
console.log(str.slice(-6, -1));  // 输出:world

6.2 搜索方法

  • indexOf(searchValue, startIndex):从指定的索引位置开始查找指定的字符串或字符,并返回首次出现的索引位置。如果未找到,返回 -1。
  • lastIndexOf(searchValue, startIndex):从指定的索引位置开始反向查找指定的字符串或字符,并返回最后一次出现的索引位置。如果未找到,返回 -1。
  • startsWith(searchValue, startIndex):判断字符串是否已指定的字符串或字符开头。
  • endsWith(searchValue, endIndex):判断字符串是否以指定的字符串或字符结尾。
  • include(searchValue, startIndex):判断字符串是否包含指定的字符串或字符。
var str = "Hello, world!";
console.log(str.indexOf("o"));  // 输出:4
console.log(str.lastIndexOf("o"));  // 输出:8
console.log(str.startsWith("Hello"));  // 输出:true
console.log(str.endsWith("world!"));  // 输出:true
console.log(str.includes("llo"));  // 输出:true

6.3 转换方法

  • toUpperCase():将字符串转换为大写。
  • toLowerCase():将字符串转换为小写。
var str = "Hello, world!";
console.log(str.toUpperCase());  // 输出:HELLO, WORLD!
console.log(str.toLowerCase());  // 输出:hello, world!

6.4 替换方法

  • replace(searchValue, replaceValue):将字符串中指定字符串或正则表达式匹配的项替换为新的字符串。
var str = "Hello, world!";
// 指定字符串
console.log(str.replace("world", "Universe"));  // 输出:Hello, Universe!
// 正则表达式----将逗号和感叹号替换为空格
var newStr = str.replace(/[,!]/g,' ')
console.log(newStr); // 输出:Hello  World 

6.5 分割/合并方法

  • split(separator):将字符串拆分为子字符串数组,使用指定的分隔符进行分割。
  • join(separator:将数组中的所有元素连接成一个字符串,使用指定的分隔符进行合并。
var str = "Apple, Banana, Mango";
console.log(str.split(", "));  // 输出:[ 'Apple', 'Banana', 'Mango' ]
var fruits = ["Apple", "Banana", "Mango"];
console.log(fruits.join(", "));  // 输出:Apple, Banana, Mango

七、排序

7.1 通过原型链上的方法进行排序

  • sort():对数组进行排序,默认按照字符串的 Unicode 编码进行排序。数组元素可为 数字字符串
  • reverse():反转数组中元素的顺序。不涉及规则,只是简单的进行元素的反转。

7.2 冒泡排序

不断比较相邻两个元素之间的大小,通过不断交换位置将最大/最小的元素移到同一侧,实现排序的方式。

const array = [3, 1, 2, 5, 4];
const n = array.length;

for (let i = 0; i < n - 1; i++) {
  for (let j = 0; j < n - i - 1; j++) {
    if (array[j] > array[j + 1]) {
      // 交换相邻的元素
      const temp = array[j];
      array[j] = array[j + 1];
      array[j + 1] = temp;
    }
  }
}

console.log(array); // 输出: [1, 2, 3, 4, 5]

7.3 选择排序

选中一个元素后,通过与未排序的元素中最大/最小的元素交换位置,实现排序。

const array = [3, 1, 2, 5, 4];
const n = array.length;

for (let i = 0; i < n - 1; i++) {
  let minIndex = i;

  for (let j = i + 1; j < n; j++) {
    if (array[j] < array[minIndex]) {
      minIndex = j;
    }
  }

  // 交换当前位置和最小元素的位置
  const temp = array[i];
  array[i] = array[minIndex];
  array[minIndex] = temp;
}

console.log(array); // 输出: [1, 2, 3, 4, 5]

7.4 快速排序

选中一个元素,将其它元素与选中元素进行比较后将数组分为两个长度不等的子数组,对子数组进行递归排序。

function quickSort(array) {
  if (array.length <= 1) {
    return array;
  }

  const pivot = array[0]; // 选择首个元素作为基准
  const left = [];
  const right = [];

  for (let i = 1; i < array.length; i++) {
    if (array[i] < pivot) {
      left.push(array[i]);
    } else {
      right.push(array[i]);
    }
  }

  return [...quickSort(left), pivot, ...quickSort(right)];
}

const array = [3, 1, 2, 5, 4];
const sortedArray = quickSort(array);

console.log(sortedArray); // 输出: [1, 2, 3, 4, 5]

7.5 堆排序

大顶堆:根节点的值一定大于它的左右子节点的值
小顶堆:根节点的值一定小于它的左右子节点的值

// 定义一个方法进行判断与调整
function heapify(arr,n,i){
	let largest = i; // 根节点下标
	let left = 2*i+1;
	let right = 2*i+2;
	if(left < n && arr[left] > arr[largest]){
		largest = left; // 交换下标
	}
	if(right < n && arr[right] > arr[i]){
		largest = right;
	}
	// 如果根节点下标变化了
	if(largest != i){
		// 交换:当前节点值 与 最大根节点值
		const temp = arr[i]
		arr[i] = arr[largest];
		arr[largest] = temp;
		
		// 因为交换了位置,所以要重新查看是否满足条件
		heapify(arr,n,largest);
	}
}

function heapSort(array) {
  const n = array.length;
  // 建堆(从最后一个元素开始)
  for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
    heapify(array, n, i);
  }
  // 排序(升序)
  for (let i = n - 1; i > 0; i--) {
      // 将堆顶元素与当前位置的元素进行交换
      const temp = array[0];
      array[0] = array[i];
      array[i] = temp;

      heapify(array, i, 0);
    }

    return array;
}

const array = [3, 1, 2, 5, 4];
const sortedArray = heapSort(array);

console.log(sortedArray); // [1,2,3,4,5]

7.6 插入排序

从第二个元素开始遍历数组,将当前元素插入到已排序部分的正确位置。

const arr = [3, 1, 2, 5, 4];
let preIndex;
let current;
for(var i = 1;i<arr.length;i++){
	preIndex = i - 1; 
	current = arr[i]; // 保存当前插入元素的值
	// 判断元素是否存在且这元素值大于当前插入元素的值
	while(preIndex >= 0 && arr[preIndex] > current){
		arr[preIndex+1] = arr[preIndex];  // 将元素向后移一位
		preIndex--; // 继续向前查询
	}
	// 找到合适位置后,插入元素
	arr[preIndex + 1] = current;	
}
console.log(arr);

7.7 归并排序

将待排序的数组通过不断递归拆分程较小的子数组,然后通过合并有序的子数组来实现排序。

  • 归并排序的主要步骤:拆分合并
  • 拆分
    • 将待排序的数组从中间分成两个较小的数组;
    • 对这两个子数组分别进行拆分,知道每个子数组只包含一个元素。
  • 合并
    • 将拆分后的子数组按照顺序逐个合并程更大的有序数组;
    • 比较两个子数组的首个元素,将较小的元素放入新的临时数组;
    • 重复上述步骤;
    • 最后将临时数组中的元素赋值回原始数组的相应位置,完成排序。
function mergeSort(array) {
  if (array.length <= 1) {
    return array; // 基线条件:如果数组长度为 1 或 0,直接返回原数组
  }

  // 拆分数组
  const mid = Math.floor(array.length / 2);
  const leftArr = array.slice(0, mid);
  const rightArr = array.slice(mid);

  // 递归拆分和合并
  const leftSorted = mergeSort(leftArr);
  const rightSorted = mergeSort(rightArr);

  // 合并排序后的数组
  return merge(leftSorted, rightSorted);
}

function merge(leftArr, rightArr) {
  let result = [];
  let leftIndex = 0;
  let rightIndex = 0;

  // 比较两个子数组的元素,将较小的元素放入新的临时数组
  while (leftIndex < leftArr.length && rightIndex < rightArr.length) {
    if (leftArr[leftIndex] < rightArr[rightIndex]) {
      result.push(leftArr[leftIndex]);
      leftIndex++;
    } else {
      result.push(rightArr[rightIndex]);
      rightIndex++;
    }
  }

  // 将剩余的元素放入临时数组
  return result.concat(leftArr.slice(leftIndex)).concat(rightArr.slice(rightIndex));
}

// 示例用法
const array = [8, 3, 9, 4, 5, 1, 6, 2, 7];
const sortedArray = mergeSort(array);
console.log(sortedArray); // 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]

7.8 希尔排序

一种基于插入排序的排序算法。通过将原始数组分割成若干个较小的子数组来进行排序,最终使用插入排序对这些子数组进行排序。

function shellSort(arr) {
  var len = arr.length;
  var gap = Math.floor(len / 2); // 初始增量为数组长度的一半
  while (gap > 0) {
    for (var i = gap; i < len; i++) {
      var temp = arr[i];
      var j = i;
      while (j >= gap && arr[j - gap] > temp) {
        arr[j] = arr[j - gap];
        j -= gap;
      }
      arr[j] = temp;
    }
    gap = Math.floor(gap / 2); // 缩小增量,直至增量为 1
  }
  return arr;
}
// 示例用法
var arr = [5, 3, 8, 4, 2];
console.log(shellSort(arr)); // 输出:[2, 3, 4, 5, 8]

八、函数

8.1 函数声明

  • 函数体声明
function fn(){
	// 函数体
}
  • 函数表达式声明
var 函数名 = function(a,b){
	return a + b;
}
  • 匿名函数
var 变量名 = function(a,b){
	return a * b;
}
  • 箭头函数
    • 简洁体:当函数体只有一条返回语句时,可以省略大括号 {} 和 return 关键字。
    // 简洁体
    (x, y) => x + y;
    
    // 等价于
    (x, y) => {
     return x + y;
    };
    
    • 块体:当函数体有多条语句时,需要使用大括号 {} 将它们括起来,并且需要明确使用 return 关键字来返回值。
    // 块体
    (x, y) => {
      console.log("A");
      return x + y;
    };
    

函数表达式声明函数和匿名函数创建函数之间的区别:

  • 命名
    • 函数表达式可以命名。
    • 匿名函数没有名称。
  • 可访问性
    • 函数表达式中的函数只能在声明后的代码行中访问。
    • 匿名函数可以在声明之前或之后的任何位置访问。

8.2 函数调用

语法:函数名()

8.3 函数封装

  • 优点:
    • 代码复用:封装的函数可以在不同的地方重复使用,避免了代码的荣誉和重复编写相同的逻辑。有效提高开发效率。
    • 抽象与封装:将一段代码逻辑进行抽象,隐藏内部实现细节,之对外暴露必要的接口。提高代码的安全性和稳定性。
    • 参数灵活性:封装的函数可以通过参数接受外部传入的数据,从而实现对不同情况的适配和处理。通过参数的灵活性,可以是函数具有更广泛的实用性。
    • 代码可维护性:将复杂的逻辑抽离出来,形成一个单独的模块,是的代码结构更加清晰和可维护。在需要修改某个共嗯那个是,只需修改封装的函数,而不需要修改调用该函数的代码,提高了代码的可维护性。

8.4 立即执行函数

在定义后立即执行的 JavaScript 函数表达式。

  • 基本语法
    (function() {
    	// 执行代码
    })();
    
  • 可以接收参数,并在调用时传入参数
    (function(message) {
    	console.log(message);
    })("Hello,World!");
    
  • 运用场景
    1. 创建私有作用域
    2. 封装模块代码
    3. 避免全局污染

九、作用域

即 在程序中定义变量的区域,决定了变量的可见性和生命周期。作用域规定了变量的访问权限,即变量可以在哪些部分被访问到。

9.1 全局作用域

最外层的作用域,它存在于整个程序的生命周期中,在任何地方都可以访问到全局作用域中声明的变量

  • 示例
    var globalVariable = 'Global';  // 全局变量
    
    function globalFunction() {    // 全局函数
      console.log('This is a global function');
    }
    
    // 全局作用域
    console.log(globalVariable);   // 输出: Global
    globalFunction();              // 输出: This is a global function
    

9.2 函数作用域

仅限于函数内部,即在函数中声明的变量只能在该函数内部访问,外部无法访问函数作用域中的变量。每次调用函数时,都会创建一个新的函数作用域。

  • 示例
    function outerFunction() {
      var outerVariable = 'Outer';  // 外部函数的变量
    
      function innerFunction() {   // 内部函数
        var innerVariable = 'Inner';  // 内部函数的变量
        console.log(outerVariable);  // 内部函数可以访问外部函数的变量
        console.log(innerVariable);
      }
    
      innerFunction();              // 在外部函数中调用内部函数
      console.log(outerVariable);
      console.log(innerVariable);   // 错误,内部变量无法在外部访问
    }
    
    outerFunction();
    

9.3 块级作用域

由一对花括号{}创建的范围,在块级作用域内部声明的变量只能在该块级作用域内访问。ES6 引入了 letconst 关键字用于创建块级作用域。

  • 示例
    // ES6之前,使用IIFE创建块级作用域
    (function() {
      var blockVariable = 'Block';  // 块级作用域变量
      console.log(blockVariable);
    })();
    
    // ES6中使用let创建块级作用域
    function blockScopeExample() {
     	if (true) {
    	let blockVariable = 'Block';  // 块级作用域变量
       	console.log(blockVariable);
      	}
      	console.log(blockVariable);    // 错误,无法在外部访问块级变量
    }
    
    blockScopeExample();
    

9.4 词法作用域

变量查找是基于源代码中变量声明的位置,而不是基于运行时的调用栈。

  • 示例
    var globalVariable = 'Global';  // 全局作用域
    
    function outerFunction() {
      	var outerVariable = 'Outer';  // 外部函数作用域
    
    function innerFunction() {
     	var innerVariable = 'Inner';  // 内部函数作用域
    
    	console.log(innerVariable);  // 可以访问内部作用域变量
    	console.log(outerVariable);  // 可以访问外部作用域变量
    	console.log(globalVariable); // 可以访问全局作用域变量
     }
      
    innerFunction();
    }
    
    outerFunction();
    

9.5 闭包

指一个函数能在其词法作用域之外的地方访问变量,即使该变量已经离开了作用域。

9.5.1闭包的特点
  • 函数内部声明的函数可以访问父函数的变量,即使夫函数已经执行完毕。
  • 闭包创建时会保存其词法作用域,因此它可以记住并访问创建时所在作用域的变量。
  • 闭包可以作为函数对象传递、返回或存储在其他变量中。
    示例
function outerFunction() {
  var outerVariable = 'I am from outer function';

  function innerFunction() {
    console.log(outerVariable);
  }

  return innerFunction;
}

var closure = outerFunction();
closure(); // 输出:I am from outer function

在上面的代码中,innerFunction是一个闭包,它可以访outerFunction中声明的 outerVariable 变量,尽管outerFunction已经执行完毕。通过调用outerFunction并将其返回值赋给closure,我们创建了一个闭包实例。随后,通过调用 closure(),闭包输出了outerVariable的值。

9.6 this关键字

在 JavaScript 中,this 关键字引用

  • 作用域链
    在作用域中,变量的查找是按照词法顺序进行的,即从最内层的作用域向外层逐级查找,直到找到第一个匹配的变量为止。这种查找方式称为作用域链(Scope Chain)。
  • 词法作用域
  • 声明提升
  • 闭包:函数可以访问其声明外部作用域的变量,即使在外部作用域已经执行结束之后仍然有效。
  • 模块化
  • 动态作用域
  • this关键字
  • with语句

未完待续……

若内容有误,欢迎指正,大家一起学习,共同进步。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值