D2-JavaScript中的函数与数组

JavaScript中的函数和数组是编程中非常重要的概念。函数可以被看作是一种代码块,它可以接受输入参数并返回一个结果。而数组则是一种有序的数据集合,可以包含任意类型的数据。本文将深入介绍二者的概念及用法。

一、JavaScript中的函数

函数是 JavaScript 中的基本组件之一。一个函数是 JavaScript 过程 ------ 一组执行任务或计算值的语句。要使用一个函数,你必须将其定义在你希望调用它的作用域内。 每个 JavaScript 函数实际上都是一个 Function 对象。运行(function(){}).constructor === Function // true便可以得到这个结论。

1. 函数的基本概念

① 如何定义函数

Ⅰ. 常规定义函数
javascript 复制代码
// 常规函数
let egg = '鸡蛋';
// Params 入参
function 微波炉(egg) {
    console.log("加热"); // 加热
    // Return 返回值
    return egg + '煮熟了';
}
// 调用函数,得到热鸡蛋
const result = 微波炉(egg);
console.log(result); // 鸡蛋煮熟了
Ⅱ. 定义箭头函数
javascript 复制代码
// 箭头函数
const washMachine = (clothes) => {
    console.log("洗衣服"); // 洗衣服
    return '干净衣服';
}
const result2 = washMachine('脏衣服');
console.log(result2); // 干净衣服
​
// 箭头函数的简写
const washMachine2 = clothes => {
    console.log("洗衣服"); // 洗衣服
    return '干净衣服';
}
const result3 = washMachine2('脏衣服');
console.log(result3); // 干净衣服

② 函数的参数

参数是传递给函数的值,可以是基本类型(如数字、字符串、布尔值)或对象类型。参数列表在括号内,多个参数之间用逗号分隔。

javascript 复制代码
function add(a, b) {
    return a + b;
}

③ 函数的返回值

函数可以使用return语句返回一个值,这个值会作为函数调用的结果。如果没有return语句,函数将返回undefined

javascript 复制代码
function multiply(a, b) {
    return a * b;
}

④ 普通函数与箭头函数的区别

Ⅰ. 箭头函数受变量提升的影响

由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要varlet const定义的时候更不必说)关键词,而var所定义的变量不能得到变量提升,故箭头函数一定要定义于调用之前!(使用let定义一键解决这个问题😁)

javascript 复制代码
foo(); //123
function foo(){
    console.log('123');
}
​
arrowFn(); //Uncaught TypeError: arrowFn is not a function
var arrowFn = () => {
    console.log('456');
};
Ⅱ. 箭头函数不会创建自己的this

我们先来看看MDN上对箭头函数this的解释。

箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this

箭头函数没有自己的this,它会捕获自己在定义时 (注意,是定义时,不是调用时)所处的外层执行环境的this ,并继承这个this值。所以,箭头函数中this的指向在它被定义的时候就已经确定了,之后永远不会改变。

来看个例子:

javascript 复制代码
var id = 'Global';
​
function fun1() {
    // setTimeout中使用普通函数
    setTimeout(function(){
        console.log(this.id);
    }, 2000);
}
​
function fun2() {
    // setTimeout中使用箭头函数
    setTimeout(() => {
        console.log(this.id);
    }, 2000)
}
​
fun1.call({id: 'Obj'});     // 'Global'
​
fun2.call({id: 'Obj'});     // 'Obj'

上面这个例子,函数fun1中的setTimeout中使用普通函数,2秒后函数执行时,这时函数其实是在全局作用域执行的,所以this指向Window对象,this.id就指向全局变量id,所以输出'Global'。 但是函数fun2中的setTimeout中使用的是箭头函数,这个箭头函数的this在定义时就确定了,它继承了它外层fun2的执行环境中的this,而fun2调用时thiscall方法改变到了对象{id: 'Obj'}中,所以输出'Obj'

再来看另一个例子:

javascript 复制代码
var id = 'GLOBAL';
var obj = {
  id: 'OBJ',
  a: function(){
    console.log(this.id);
  },
  b: () => {
    console.log(this.id);
  }
};
​
obj.a();    // 'OBJ'
obj.b();    // 'GLOBAL'

上面这个例子,对象obj的方法a使用普通函数定义的,普通函数作为对象的方法调用时,this指向它所属的对象 。所以,this.id就是obj.id,所以输出'OBJ'。 但是方法b是使用箭头函数定义的,箭头函数中的this实际是继承的它定义时所处的全局执行环境中的this,所以指向Window对象,所以输出'GLOBAL'。(这里要注意,定义对象的大括号{}是无法形成一个单独的执行环境的,它依旧是处于全局执行环境中!!

Ⅲ. 箭头函数不能作为构造函数使用

我们先了解一下构造函数的new都做了些什么?简单来说,分为四步: ① JS内部首先会先生成一个对象; ② 再把函数中的this指向该对象; ③ 然后执行构造函数中的语句; ④ 最终返回该对象实例。

但是!!因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!

javascript 复制代码
let Fun = (name, age) => {
    this.name = name;
    this.age = age;
};
​
// 报错
let p = new Fun('cao', 24);

2. 函数的用法

① 函数声明

使用关键字function声明一个函数,后面跟函数名、参数列表和函数体。

javascript 复制代码
function functionName(parameters) {
  // 函数体
}

② 函数调用

通过函数名加括号的方式调用函数,并传入相应的参数。

javascript 复制代码
var result = functionName(arguments);

3. 函数的作用域

在JavaScript中,作用域是指变量的可见性范围。函数内部定义的变量从函数外部是不可访问的(不可见的),而在函数内部可以访问,每个函数都会默认创建一个作用域。

javascript 复制代码
function fn1(){
	let a=1
}
console.log(a)  // a不存在

function fn2(){
 	let a=1
}
fn2()
console.log(a)  // a还是不存在

这也就引申出了全局变量和局部变量的概念,在JavaScript中,全局变量是在函数外部定义的变量,拥有全局作用域,即在JavaScript代码的任何地方都可以访问。而局部变量是定义在函数内部,只能在函数中使用的变量,作用范围是从函数开始到结尾,即在{}里 。

javascript 复制代码
var globalVar = "我是全局变量";

function exampleFunction() {
  var localVar = "我是局部变量";
  console.log(globalVar); // 输出 "我是全局变量"
  console.log(localVar); // 输出 "我是局部变量"
}

exampleFunction();
console.log(globalVar); // 输出 "我是全局变量"
console.log(localVar); // 报错 "undefined"

4. argumentsthis

arguments 对象是所在函数的一个内置类数组对象,每个函数都有一个 arguments 属性,表示函数的实参集合,即执行函数时实际传入的参数的集合。arguments 不是数组而是一个对象,但它和数组很相似,所以通常称为类数组对象。arguments 对象不能显式的创建,它只有在函数开始时才可用。下面是一些常见情况下arguments的用法:

  • arguments.length返回传递给函数的实参个数。
  • arguments[index]返回传递给函数的第index个实参。

下面是一个简单的例子来说明这个概念:

javascript 复制代码
function fn(){
  console.log(arguments)
}

在JavaScript中,this关键字是一个特殊的变量,它指向当前执行上下文中的对象。this的值取决于函数是如何被调用的。下面是一些常见情况下this的值:

  • 在全局作用域中,this指向全局对象(在浏览器中是window对象)。
  • 在普通函数中,this指向调用该函数的对象。
  • 在构造函数中,this指向新创建的实例对象。
  • 在事件处理程序中,this指向触发事件的元素。
  • 在使用call()、apply()或bind()方法调用函数时,this指向传入的第一个参数。

下面是一个简单的例子来说明这个概念:

javascript 复制代码
function Person(name) {
  this.name = name;
}
​
Person.prototype.sayHello = function() {
  console.log('Hello, my name is ' + this.name);
};
​
var person1 = new Person('Alice');
person1.sayHello(); // 输出 "Hello, my name is Alice"

二、JavaScript中的数组

在 JavaScript 中,数组不是基本类型,而是具有以下核心特征的 Array 对象

  • JavaScript 数组是可调整大小的,并且可以包含不同的数据类型。(当不需要这些特征时,可以使用类型化数组。)
  • JavaScript 数组不是关联数组,因此,不能使用任意字符串作为索引访问数组元素,但必须使用非负整数(或它们各自的字符串形式)作为索引访问。
  • JavaScript 数组的索引从 0 开始 :数组的第一个元素在索引 0 处,第二个在索引 1 处,以此类推,最后一个元素是数组的length 属性减去 1 的值。
  • JavaScript 数组复制操作创建浅拷贝。(所有 JavaScript 对象的标准内置复制操作都会创建浅拷贝,而不是深拷贝)。

1. 数组的创建与转换

① 数组的创建

javascript 复制代码
// 1.字面量创建
let arr1 = [1,2,3];
console.log(arr1); // [1, 2, 3]
// 2.构造函数创建
let arr2 = new Array(1,2,3);
console.log(arr2); // [1, 2, 3]
// 3.通过Array.of()方法创建
let arr3 = Array.of(1,2,3);
console.log(arr3); // [1, 2, 3]

② 字符串转为数组

javascript 复制代码
let str = 'hello world';
// 1.split() 方法用于把一个字符串分割成字符串数组
let strArr = str.split(' ');
console.log(strArr); // ["hello", "world"]
// 2.Array.from() 方法默认把每一个字符都分割出来
let strArr2 = Array.from(str);
console.log(strArr2); // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]

③ 对象转为数组

javascript 复制代码
let obj = {
    name: 'jack',
    age: 18
}
// 1.Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组
let objArr = Object.keys(obj);
console.log(objArr); // ["name", "age"]
// 2.Object.values() 方法返回一个给定对象自身的所有可枚举属性值的数组
let objArr2 = Object.values(obj);
console.log(objArr2); // ["jack", 18]
// 3.Array.from() 方法也可以把对象转换成数组
let obj2 = {
    0: 'a',
    1: 'b',
    2: 'c',
    length: 3
}
let objArr3 = Array.from(obj2);
console.log(objArr3); // ["a", "b", "c"]

④ 数组的截取和拼接

javascript 复制代码
let arr = [1,2,3,4,5,6,7,8,9];
// slice() 方法可从已有的数组中返回选定的元素,即截取数组
let arr2 = arr.slice(2,5);
console.log(arr2); // [3, 4, 5]
// concat() 方法用于连接两个或多个数组,即拼接数组
let shortArr1 = [1,2,3];
let shortArr2 = [4,5,6];
let longArr = shortArr1.concat(shortArr2);
console.log(longArr); // [1, 2, 3, 4, 5, 6]
// 三点运算符可以将数组展开,相当于把数组中的每一项都取出来,再放到一个新的数组中
let longArr2 = [...shortArr1,...shortArr2];
console.log(longArr2); // [1, 2, 3, 4, 5, 6]

2. 数组的增删改查

① 向数组中增添元素

Ⅰ. push()

可向数组的末尾添加一个或多个元素,并返回新的长度

javascript 复制代码
let arr = [1,2,3];
let arrPush = arr.push(4,5,6);
console.log(arr); // [1, 2, 3, 4, 5, 6]
console.log(arrPush); // 6
// 但是不能添加数组,它会把数组当成一个元素添加在末尾
arr.push([7,8,9]);
console.log(arr); // [1, 2, 3, 4, 5, 6, Array(3)]
// 只能借助三点运算符来添加数组
arr.push(...[7,8,9]);
console.log(arr); // [1, 2, 3, 4, 5, 6, Array(3), 7, 8, 9]
Ⅱ. unshift()

可向数组的开头添加一个或多个元素,并返回新的长度

javascript 复制代码
let arr2 = [1,2,3];
let arrUnshift = arr2.unshift(4,5,6);
console.log(arr2); // [4, 5, 6, 1, 2, 3]
console.log(arrUnshift); // 6
// 但是不能添加数组,它会把数组当成一个元素添加在开头
arr2.unshift([7,8,9]);
console.log(arr2); // [Array(3), 4, 5, 6, 1, 2, 3]
// 只能借助三点运算符来添加数组
arr2.unshift(...[7,8,9]);
console.log(arr2); // [7, 8, 9, Array(3), 4, 5, 6, 1, 2, 3]
Ⅲ. splice()

可向数组的任意位置添加一个或多个元素,也兼具删除和修改的功能

javascript 复制代码
// 语法:arrayObject.splice(开始下标,删除的个数,需要添加的元素)
let months = ['Jan', 'March', 'April', 'June'];
// 从索引1开始删除0个元素,然后插入'Feb'
months.splice(1, 0, 'Feb');
console.log(months); // ["Jan", "Feb", "March", "April", "June"]
// 从索引4开始删除0个元素,然后插入'May'
months.splice(4, 0, 'May');
console.log(months); // ["Jan", "Feb", "March", "April", "May", "June"]
// 将七月至十二月都加进来
months.splice(6, 0, 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec');
console.log(months); // ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"]

② 从数组中删除元素

Ⅰ. pop()

能够删除并返回数组的最后一个元素

javascript 复制代码
let arr3 = [1,2,3];
let arrPop = arr3.pop();
console.log(arr3); // [1, 2]
console.log(arrPop); // 3
Ⅱ. shift()

能够把数组的第一个元素从其中删除,并返回第一个元素的值

javascript 复制代码
let arr4 = [1,2,3];
let arrShift = arr4.shift();
console.log(arr4); // [2, 3]
console.log(arrShift); // 1
Ⅲ. splice()

可向数组的任意位置删除一个或多个元素,也兼具添加和修改的功能

javascript 复制代码
let months2 = ['Jan', 'Feb', 'March', 'April', 'May', 'June', 'July', 'Aug'];
// 从索引0开始删除1个元素
months2.splice(0, 1);
console.log(months2); // ["Feb", "March", "April", "May", "June", "July", "Aug"]

③ 修改数组元素

javascript 复制代码
// 直接通过索引修改数组中的元素
var arr = [1, 2, 3];
arr[0] = 4; // 将第一个元素修改为4
console.log(arr); // 输出[4, 2, 3]

// splice()方法修改数组中元素
let months3 = ['Jan', 'Feb'];
// 从索引0开始删除1个元素,然后插入'一月'
months3.splice(0, 1, '一月');
console.log(months3); // ["一月", "Feb"]

④ 查找数组元素

javascript 复制代码
// 1.通过索引查找
let arr5 = [1,2,3];
console.log(arr5[0]); // 1
// 2.通过值查找索引
const index = arr5.indexOf(3);
console.log(index); // 2
// 3.通过find()方法查找
// find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
const arr6 = [
    {id: 1, name: 'jack'},
    {id: 2, name: 'rose'},
    {id: 3, name: 'tom'}
]
const obj = arr6.find(function(item){
    return item.id === 2;
})
console.log(obj); // {id: 2, name: "rose"}

⑤ 判断数组中是否包含某个值

javascript 复制代码
let arr7 = [1,2,3];
// includes()方法
const isInArr = arr7.includes(3);
console.log(isInArr); // true
const isInArr2 = arr7.includes(6);
console.log(isInArr2); // false
// indexof()方法
const isInArr3 = arr7.indexOf(3);
const isInArr4 = arr7.indexOf(6);
if (isInArr3 >= 0){
    console.log('包含'); // 包含
}
if (isInArr4 < 0){
    console.log('不包含'); // 不包含
}

3. 遍历数组

for 循环

javascript 复制代码
let arr = [1,2,3,4,5];
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

forEach 方法

javascript 复制代码
// 对原数组没有影响,没有返回值
let arr1 = [1,2,3,4,5];
// forEach接受一个函数作为参数
arr1.forEach((item,index)=>{
    console.log(`${item}-${index}`); // 1-0 2-1 3-2 4-3 5-4
    item = item*2;
})
console.log(arr1); // [1, 2, 3, 4, 5]

map 映射

javascript 复制代码
// 跟forEach一样,接受一个函数作为参数
// 不同的是,map会将执行结果组成一个新的数组返回
// map不会对原数组产生影响
let arr2 = [1,2,3,4,5];
// double函数的作用是将数组中的每个元素都乘以2
const double = (arr)=>{
    return arr.map((item)=>{
        return item*2;
    })
}
console.log(double(arr2)); // [2, 4, 6, 8, 10]

some 方法

javascript 复制代码
// 用于检测数组中是否有满足条件的元素
// 如果有,返回true,否则返回false
let arr3 = [1,2,3,4,5];
// some方法接受一个函数作为参数
const res=arr3.some((item)=>{
    return item>3;
})
console.log(res); // true
const res2=arr3.some((item)=>{
    return item>5;
})
console.log(res2); // false

every 方法

javascript 复制代码
// 用于检测数组中是否所有元素都满足条件
// 如果是,返回true,否则返回false
let arr4 = [1,2,3,4,5];
// every方法接受一个函数作为参数
const res3=arr4.every((item)=>{
    return item>3;
})
console.log(res3); // false
const res4=arr4.every((item)=>{
    return item>0;
})
console.log(res4); // true

findIndex 方法

javascript 复制代码
// 用于查找数组中是否有满足条件的元素 返回下标
// 如果有,返回满足条件的元素的下标 如果没有,返回-1
let arr5 = [1,2,3,{
    name:'jack',
    age:18
}];
// findIndex方法接受一个函数作为参数
const res5=arr5.findIndex((item)=>{
    return item>3;
})
console.log(res5); // -1
const res6=arr5.findIndex((item)=>{
    return name = 'jack';
})
console.log(res6); // 0

find 方法

javascript 复制代码
// 用于查找数组中是否有满足条件的元素 返回元素
// 如果有,返回满足条件的元素 如果没有,返回undefined
let arr6 = [1,2,3,{
    name:'jack',
    age:18
}];
// find方法接受一个函数作为参数
const res7=arr6.find((item)=>{
    return item>2;
})
console.log(res7); // 3
const res8=arr6.find((item)=>{
    return name = 'jack';
})
console.log(res8); // 1

filter 方法

javascript 复制代码
// 用于查找数组中是否有满足条件的元素 过滤
// 如果有,返回满足条件的元素组成的数组 如果没有,返回空数组
let arr7 = [1,2,3,4,5];
// filter方法接受一个函数作为参数
const res9=arr7.filter((item)=>{
    return item>3;
})
console.log(res9); // [4, 5]
const res10=arr7.filter((item)=>{
    return item>5;
})
console.log(res10); // []
相关推荐
Jiaberrr39 分钟前
uniapp中使用原生ajax上传文件并携带其他数据,实时展示上传进度
前端·javascript·vue.js·ajax·uni-app
小牛itbull1 小时前
ReactPress:深入解析技术方案设计与源码
javascript·react.js·reactpress
alexbai!1 小时前
el-date-picker picker-options属性中disabledDate设置时间的禁用和启用,并且支持到时分秒的禁用和启用
javascript·vue.js·elementui
学无止境鸭2 小时前
vue读取本地excel文件并渲染到列表页面
前端·javascript·vue.js
ClinEvol2 小时前
JAVA后端生成图片滑块验证码 springboot+js完整案例
java·javascript·spring boot·滑块验证码
姚家湾2 小时前
由播客转向个人定制的音频频道(1)平台搭建
javascript·ai·hls·ardunio·播客
孩子 你要相信光3 小时前
sanitize-html 防止 XSS(跨站脚本攻击)
前端·javascript·html
爱吃糖的范同学3 小时前
【前端学习指南】第三站 Vue 组件之间通信
开发语言·前端·javascript·vue.js·前端框架·ecmascript
A_cot5 小时前
Vue.js:构建现代 Web 应用的强大框架
前端·javascript·vue.js·flutter·html·web·js