JavaScript青少年简明教程:函数及其相关知识(上)

news2024/11/16 10:48:30

JavaScript青少年简明教程:函数及其相关知识(上)

在JavaScript中,函数是一段可以重复使用的代码块,它执行特定的任务并可能返回结果。

内置函数(Built-in Functions)

内置函数是编程语言中预先定义的函数,也可以称为标准库函数(Standard Library Functions)。这些函数由编程语言的引擎或标准库提供,开发者可以直接使用它们来完成常见的任务,而无需自己实现相应的功能。例如,JavaScript的Math对象就包含了一系列数学相关的内置函数,如Math.abs()、Math.sin()等。

本节重点介绍自定义函数。

自定义函数

先看常见的命名函数

命名函数使用function关键字来定义,后面跟着函数名和一对圆括号内的参数列表,以及大括号内的函数体。格式:

function functionName(parameter1, parameter2, ...) {

  // 函数体

  // 在这里编写要执行的代码

}

其中,functionName 是函数的名称;parameter1, parameter2, ... 是函数的参数——形参。函数体内编写了要执行的代码。

命名函数的调用:

functionName(argument1, argument2, ...);

其中,functionName 是函数的名称;argument1,argument2, ... 是实参。

例如

// 定义函数
function greet(name) {
    return "Hello, " + name;
}

let message = greet("Alice"); // 调用函数
console.log(message);

JavaScript的函数是定义和组织代码的基本构建块之一。一个函数是一组语句的集合,可以在代码中多次调用。函数能够接受输入(称为参数)并返回输出(称为返回值)。

函数的调用

要执行函数中的代码,你需要调用(或执行)该函数。这可以通过在函数名后添加括号(即使该函数不接受任何参数)来完成。

基本函数语法

functionName(argument1, argument2, ..., argumentN)

functionName: 是你要调用的函数的名称。

(): 圆括号是函数调用的标志。

argument1, argument2, ..., argumentN: 是传递给函数的参数(如果有的话)

例如:

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

// 调用时传递数字  
add(1, 2); // sum 是 3  

顺便指出下面情况

 也可以传递字符串,尽管这不是期望的用法 

add('1', '2'); // result 是 '12',因为字符串连接了

说明:在 JavaScript 中,+ 运算符既可以用于数字相加,也可以用于字符串拼接。如果 a 或 b 中有一个是字符串,+ 会进行字符串拼接。

嵌套调用

add(2, add(3, 4));  // 输出: 9

嵌套函数调用并不是 JavaScript 独有的特性。许多其他编程语言(如Python、C++、Java等)也支持这种方式。

形参(parameter)和实参(argument)是在函数定义和函数调用时使用的术语。

形参是在定义函数时,括号内部列出的变量名称。它们是函数内部使用的占位符,用于接收将来调用该函数时传入的值。

实参是在调用函数时,括号内部传递给函数形参的具体值。

实参会依次映射到形参上。

函数的参数传递

在JavaScript中,函数参数都是按值传递的。也就是说,传递给函数的是参数值的拷贝。但是对于不同数据类型,这个“值”的内容是有区别的,对于对象参数,这个“值”是对象的引用。

参数传递方面,在 JavaScript中,参数传递方式是按值传递——传递的是副本。具体说来:1)当将一个原始(基本)类型(primitive type)数据如数字、字符串、布尔值等作为参数传递给函数时,实际上是将该值的一个副本传递给函数——将实参值复制给形参,实参和形参相互独立互不干扰。函数内部对该副本的修改不会影响到原始的值。2)当将一个引用数据类型(对象类型)(如对象、数组等)作为参数传递给函数时,传递的是该对象的引用(地址)的副本——将实参引用的地址值复制给形参,形参和实参指向同一个对象的地址,改变形参所指向的对象的属性将影响实参所指向的对象。需要注意,在引用类型的参数传递中,并不会改变形参的值(即引用的地址),而是通过形参改变它所指向的对象的属性。

☆当传递原始数据类型时,实际上是将原始值的副本传递给了函数或其他变量。这意味着函数或其他变量操作的是原始值的副本,而不是原始值本身。

这种传递方式使得函数内部对原始值的修改不会影响到函数外部的变量,因为函数内部操作的是原始值的副本,而不是原始值本身。

例如:

function addTen(num) { // num 是一个局部变量
    num += 10;
    return num;
}

let count = 20;
let result = addTen(count);
console.log(count);   // 20,没有变化
console.log(result);   // 30

解析如下:

此例展示了在 JavaScript 中传递变量的值的方式。

例中定义了一个函数 addTen,它接受一个参数 num。

在此主要关注变量情况:

首先,定义了一个变量 count,并赋值为 20。

接下来,调用 addTen 函数,并将 count 作为参数传递进去。这里需要注意的是,虽然 count 的值是 20,但是在函数中传递的是 count 的值的副本,而不是 count 本身。

在函数内部,num 的值被增加了 10,变成了 30。然后,函数返回了这个新的值,并将其赋给了变量 result。

最后,通过 console.log 打印了 count 和 result 的值。由于在函数中传递的是 count 的值的副本,所以 count 的值没有发生变化,仍然是 20。而 result 的值是函数返回的新值,即 30。图解如下:

☆当传递引用数据类型(reference type)数据如对象、数组时,实际上是将引用的地址传递给了函数。这意味着函数可以通过引用来访问和修改原始对象。引用是指向存储在内存中的对象的地址,所以传递引用时,传递的是指向对象的指针,而不是对象本身的实际值。

这种传递方式使得我们可以在函数内部修改原始对象,并且这些修改会在函数外部可见。因为函数和外部变量都指向同一个对象,所以对对象的修改会影响到所有引用该对象的变量。

例如:

function changeName(obj) {
    obj.name = 'Bob';
}

let person = { name: 'Alice' };
console.log(person.name); // 输出 'Alice'

changeName(person);
console.log(person.name); // 输出 'Bob'

解析如下:

此例展示了在 JavaScript 中传递对象的引用的方式。

例中定义了一个函数 changeName,它接受一个参数 obj。

在此主要关注变量情况:

首先,定义了一个对象 person,并赋值为 { name: 'Alice' }。这个对象有一个 name 属性,其初始值为 ‘Alice’。

接下来,通过 console.log 打印了 person.name 的值,即 ‘Alice’。

然后,调用 changeName 函数,并将 person 对象作为参数传递进去。这里需要注意的是,虽然 person 是一个对象,但是在函数中传递的是 person 对象的引用,而不是对象本身的副本。

在函数内部,通过修改 obj 的 name 属性,将其值改为 ‘Bob’。由于 obj 是 person 对象的引用,所以这个修改也会影响到 person 对象本身。

最后,通过 console.log 打印了 person.name 的值,即 ‘Bob’。由于在函数中修改了 person 对象的 name 属性,所以 person.name 的值变成了 ‘Bob’。图解如下:

总结之,传递引用时,传递的是引用的地址,而不是实际的值。传递原始数据类型时,传递的是实际的值的副本。这种差异导致了在函数内部对引用数据类型的修改会影响到函数外部的变量,而对原始数据类型的修改不会影响到函数外部的变量。

为加深理解,下面再给出两个示例说明。

例1、对于原始类型(primitive type)如数字、布尔值、字符串等,传递的就是这个值本身。在函数体内对形参的任何修改,都不会影响实参变量的值。例如:

function changeNum(x) {
  x = 100; // 修改形参x的值为100
}

let num = 10;
changeNum(num);
console.log(num); // 输出10

在这个例子中,num变量的值10作为实参传递给changeNum函数。但在函数内部将形参x重新赋值为100,并不会影响到外部实参num的值。所以最后打印出来的num值仍然是10。

例2、对于引用类型(reference type)如对象、数组等,传递的值是对象的引用。如果在函数体内通过形参引用修改了对象的属性,实参对象的内容也会被修改,因为它们引用的是同一个对象。但如果在函数内部给形参变量重新赋值另一个对象,实参对象本身是不受影响的。如:


function changeArr(arr) {
  arr.push(4); // 修改数组内容
  arr = [1, 2]; // 重新赋值数组
}

let numbers = [1, 2, 3];
changeArr(numbers);
console.log(numbers); // 输出 [1, 2, 3, 4]

在这个例子中,将数组 [1, 2, 3] 作为实参传递给 changeArr 函数。在函数内部,通过形参 arr 调用 push 方法,向数组追加了一个新元素 4。由于形参和实参引用的是同一个数组,所以实参 numbers 的内容也发生了改变。接下来,将一个新的数组 [1, 2] 赋值给了形参 arr。但是,这个赋值操作只在函数内部生效,实参 numbers 指向的数组没有改变。所以最后输出的 numbers 是 [1, 2, 3, 4]。

理解清楚JavaScript的参数传递方式,可以帮助我们更好地掌控代码的执行过程,减少隐蔽的bug。

学习过其它语言的朋友注意,与Java、C#语言不同,JavaScript的参数传递不检查实参数量和形参数量是否匹配。在JavaScript中,如果你调用的函数提供的参数(实参)少于声明的参数(形参),那么未被传值的形参将被赋予undefined。如果提供的实参多于形参,那么多余的实参将不会被函数内部直接使用,但它们仍然可以通过arguments对象(在非箭头函数中)或剩余参数(rest parameters,使用...语法)来访问。

当实参数量少于形参数量时,未被传值的形参将被自动赋值为undefined,例如:

function multiply(a, b) {
  console.log(a, b); // 输出: 2, undefined
  return a * b;
}

console.log(multiply(2)); // 输出: NaN

当实参数量多于形参数量时,多余的实参虽然不能直接在函数内部通过形参名称访问,但仍然可以通过arguments对象或剩余参数来获取:

function sum(a, b) {
  let result = a + b;
  for (let i = 2; i < arguments.length; i++) {
    result += arguments[i];
  }
  return result;
}

console.log(sum(1, 2, 3, 4)); // 输出: 10

在这个例子中,sum函数只有两个形参a和b,但我们传递了四个实参。通过arguments对象,我们可以在函数内部访问所有实参。

使用剩余参数可以更方便地处理多余的实参:

function sum(a, b, ...numbers) {
  let result = a + b;
  for (let value of numbers) {
      console.log(value);
  }
  return result;
}

console.log(sum(1, 2, 10, 20));

这里,这里 a 接收 1,b 接收 2,而 ...numbers 收集 10 和 20。

for...of 循环打印了 10 和 20

函数返回 result,即 3

输出:

10
20
3

变量作用域(scope

JavaScript 中的作用域(scope)指的是变量可访问范围。主要有以下几种作用域:

☆全局作用域

全局作用域是最外层的作用域,在任何地方都可以访问全局作用域中的变量。如:

var globalVar = "I'm global";

function testScope() {
    console.log(globalVar);  // 可以访问全局变量
}

testScope();  // 输出: I'm global
console.log(globalVar);  // 输出: I'm global

☆函数作用域

函数作用域是指在函数内部声明的变量,只能在该函数内部访问。如:

function testFunctionScope() {
    var localVar = "I'm local";
    console.log(localVar);  // 可以访问
}

testFunctionScope();  // 输出: I'm local
// console.log(localVar);  // 错误:localVar is not defined

☆块级作用域 (ES6引入)

使用let和const关键字声明的变量具有块级作用域,只在声明它们的块(由 {} 包围)内有效。如:

if (true) {
    let blockVar = "I'm in a block";
    console.log(blockVar);  // 输出: I'm in a block
}
// console.log(blockVar);  // 错误:blockVar is not defined

for (let i = 0; i < 3; i++) {
    console.log(i);  // 输出: 0, 1, 2
}
// console.log(i);  // 错误:i is not defined

☆词法作用域(Lexical Scope)

词法作用域,也称为静态作用域,是指变量的作用域在代码编写时(词法分析时)就已经确定,而不是在运行时确定。在 JavaScript 中,函数的作用域在函数定义时就已经确定,而不是在函数调用时。

关键点:

内部函数可以访问外部函数的变量。

作用域是基于函数的嵌套关系,而不是函数的调用关系。

这种机制使得闭包成为可能。词法作用域的一个重要应用。

示例:

let globalVar = "I'm global";

function outerFunction() {
    let outerVar = "I'm from outer";

    function innerFunction() {
        let innerVar = "I'm inner";
        console.log(globalVar);  // 可以访问全局变量
        console.log(outerVar);   // 可以访问外部函数的变量
        console.log(innerVar);   // 可以访问自己的变量
    }

    innerFunction();
    // console.log(innerVar);  // 错误:innerVar 在这里不可访问
}

outerFunction();
// console.log(outerVar);  // 错误:outerVar 在这里不可访问

在这个例子中,innerFunction 可以访问它自己的变量、外部函数 outerFunction 的变量,以及全局变量。这就是词法作用域的体现。

变量提升

“语法基础”一节中提到过变量提升,学过函数理解更容易了。

变量提升是 JavaScript 中的一种机制,它将变量和函数的声明移动到它们所在作用域的顶部。这意味着无论你在哪里声明变量和函数,它们都会被视为在当前作用域的开始处声明。

关键点:

只有声明会被提升,赋值不会。

函数声明会被完整地提升。

变量声明使用 var 关键字时会被提升,但 let 和 const 不会(它们会产生暂时性死区)。

console.log(x);  // 输出:undefined
var x = 5;

// 上面的代码等同于:
var x;
console.log(x);
x = 5;

// 函数提升
sayHello();  // 输出:"Hello!"

function sayHello() {
    console.log("Hello!");
}

// let 和 const 不会被提升
console.log(y);  // 抛出 ReferenceError
let y = 10;

函数表达式(Function Expression)

【function expression - JavaScript | MDN 】

函数表达式也是定义函数的一种方式,但函数是赋值给一个变量的。

JavaScript 函数表达式是一种在表达式中定义函数的方式。它允许将函数作为值进行赋值、传递给其他函数或存储在变量中。

函数表达式的语法如下:

letVariableName = function [name](parameters) {

  // 函数体

};

其中,name 是函数的名称,函数名,该名称仅是函数体的局部名称——在外部作用域中不可见。可以省略。当省略函数名的时候,该函数就成为了匿名(anonymous)函数。parameters 是函数的参数列表,而函数体则是具体的代码块。

函数表达式的调用:

VariableName(argument)

其中,argument,实参,是在调用函数时传递给函数形参的具体值。

匿名函数表达式,例如:

const x = function (y) {
  return y * y;
};

console.log( x(2)); //输出 4

具名函数表达式,例如:

let sum = function add(a, b) {
    return a + b;
};

console.log(sum(3,5)); // 输出 8
//console.log(add(3,5)); // 这会抛出错误: add is not defined,因为add在这里不可见

注意,具名函数表达式,这里的函数名在外部作用域中不可见。

这种特性的主要用途递归等:递归函数可以在内部调用自己,而不需要依赖外部的变量名。例如:

const factorial = function calc(n) {
    if (n <= 1) return 1;
    return n * calc(n - 1);  // 这里可以使用 calc
};

console.log(factorial(5));  // 输出: 120
//console.log(calc(5));    // ReferenceError: calc is not defined

在这个例子中,calc 只在函数内部可见,这允许函数进行递归调用,同时不会污染外部作用域。关于递归函数后面将介绍。

ES6引入了箭头函数,这是匿名函数的一种简洁写法。下一节介绍。

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

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

相关文章

TinyMCE一些问题

1.element 在el-dialog中使用tinymce导致富文本弹窗在el-dialog后面的问题 原因是富文本的弹窗层级太低了 在APP.vue中添加样式即可解决 /* 富文本菜单 */ .tox-tinymce-aux {z-index: 9999 !important; }2.element 在el-dialog中点击富文本的功能栏报错 由于 aria-hidden 属…

系统架构设计师 - 知识产权与标准化

知识产权与标准化 知识产权与标准化&#xff08;3分&#xff09;保护范围与对象 ★ ★ ★ ★法律法规 保护期限 ★ ★知识产权人确定 ★ ★ ★ ★侵权判断 ★ ★ ★ ★标准化&#xff08;了解&#xff09;★标准的分类标准的编号 大家好呀&#xff01;我是小笙&#xff0c;本章…

WebSocket程序设计

协议说明 WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。Websocket主要用在B/S架构的应用程序中&#xff0c;在 WebSocket API 中&#xff0c;浏览器和服务器只…

Redis缓存数据库进阶——Redis与分布式锁(6)

分布式锁简介 1. 什么是分布式锁 分布式锁是一种在分布式系统环境下&#xff0c;通过多个节点对共享资源进行访问控制的一种同步机制。它的主要目的是防止多个节点同时操作同一份数据&#xff0c;从而避免数据的不一致性。 线程锁&#xff1a; 也被称为互斥锁&#xff08;Mu…

捷配告诉你半孔是如何做出来的

在PCB设计和制造领域&#xff0c;电镀半孔&#xff08;也称为齿形孔&#xff09;是一种创新技术&#xff0c;它通过焊接为单独的PCB模块提供了一种节省空间的互连方式。捷配在生产过程中经常遇到客户对这种技术的询问&#xff0c;以下是对其工作原理、设计指南和制造工艺的介绍…

Java1.3标准之重要特性及用法实例(十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列…

唯美贺卡制作QQ微信小程序完整源码/无需后台直接运营

这是一款用于发送唯美贺卡的一个小程序&#xff0c;界面唯美简洁&#xff0c;无需后台可直接运营&#xff0c;可以自定义卡片内容图标、邮票等元素&#xff0c;QQ微信小程序都可以直接使用&#xff0c;对接了部分广告&#xff0c;大家可以根据自己的广告id进行替换。 小程序主…

Linux驱动开发——字符设备驱动开发

1 概述 1.1 说明 本文是学习rk3568开发板驱动开发的记录&#xff0c;代码依托于rk3568开发板 1.2 字符设备介绍 字符设备是 Linux 驱动中最基本的一类设备驱动&#xff0c;字符设备就是一个一个字节&#xff0c;按照字节流进行读写操作的设备&#xff0c;读写数据是分先后顺…

第05课 Scratch入门篇:海底世界-多彩的鱼

海底世界-多彩的鱼 入门篇适合新手&#xff0c;如您已经学过&#xff0c;可以忽略本节课&#xff01; 故事背景&#xff1a; 蔚蓝的海洋底部有一群凶猛的鲨鱼和一群色彩斑斓的小鱼&#xff0c;还有变色的水母&#xff0c;敲打乐器的章鱼&#xff0c;还有一些能够变色的小鱼畅…

在Ollama运行HuggingFace下载的模型

本地运行模型我之前都直接使用LM-studio&#xff0c;好用、无脑。本地用足够了。但是放在服务器上才是正道&#xff0c;本地运行无法长时间开启保持运行&#xff0c;而且Ollama推出了并行GPU计算之后可用性大幅提升&#xff0c;可用性很高。 今天研究下如何用Ollama如何在本地来…

Python 教程(六):函数式编程

目录 专栏列表前言函数定义参数返回值 示例函数类型普通函数空函数匿名函数&#xff08;Lambda 函数&#xff09;嵌套函数函数装饰器高阶函数 函数参数位置参数默认参数可变位置参数可变关键字参数 函数属性和方法__name____doc__func.__dict__func.__defaults__func.__annotat…

如何为 5G 小型基站部署选择振荡器

5G 网络频谱频率更高、覆盖范围更短&#xff0c;因此比前几代网络密度更高。超高速 5G 回程 (mmWave) 在很大程度上依赖于小型基站&#xff0c;不仅是为了覆盖范围&#xff0c;也是为了速度。除此之外&#xff0c;O-RAN 联盟等举措为 RAN 生态系统提供了更多选择&#xff0c;但…

html+css 实现多选按钮动画(input checkbox按钮)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…

Vue3(二):computed、watch、生命周期、hooks

一、computed计算属性 <template><div class"person"> <!-- <input type"text" v-model"{{ firstName }}"> <input type"text" v-model"{{ lastName }}"> --><h1>一个人的信息</h1…

爬虫-通过几个例子来说明并发以及多线程

并发 什么是并发&#xff1f;并发&#xff0c;在操作系统中&#xff0c;是指一个时间段中有几个程序都处于已启动运行到运行完毕之间&#xff0c;且这几个程序都是在同一个处理机上运行&#xff0c;但任一个时刻点上只有一个程序在处理机上运行。 嗯&#xff0c;字认识&#…

vulntarget-b

实际部署之后centos7 的ip有所变动分别是 :192.168.127.130以及10.0.20.30 Centos7 老规矩还是先用fscan扫一下服务和端口&#xff0c;找漏洞打 直接爆出来一个SSH弱口令…&#xff0c;上来就不用打了&#xff0c;什么意思&#xff1f;&#xff1f;&#xff1f; 直接xshell…

快递员送包裹与一致性哈希的关系

一致性哈希&#xff08;Consistent Hashing&#xff09;是一种用于分布式系统中数据分布和负载均衡的哈希技术。它通过减少数据迁移、支持动态扩展和高容错等特点&#xff0c;在分布式缓存、存储、负载均衡等系统中有广泛应用。以下是对一致性哈希的详细介绍&#xff1a; 一致…

跨境电商平台评论管理:如何避免评论被删及提高留评率

在跨境电商领域&#xff0c;评论对于产品的销售和品牌形象至关重要。然而&#xff0c;卖家常常面临评论被删除的问题&#xff0c;这不仅影响了产品的曝光和销售&#xff0c;还可能对店铺声誉造成损害。本文将探讨亚马逊、Ozon、速卖通、Lazada等跨境电商平台评论被删除的原因&a…

财务分析,奥威BI行计算助力财务解放报表工作

【财务分析&#xff0c;奥威BI行计算助力财务解放报表工作】 在企业的财务管理体系中&#xff0c;财务报表的编制与分析是至关重要的一环。然而&#xff0c;传统的手工编制报表方式不仅耗时耗力&#xff0c;还难以应对日益复杂多变的财务数据需求。奥威BI&#xff08;Business…

2024最火的知识付费系统小程序+PC+H5三端数据互通支持采集资源开源版

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 系统含带 裂变模式 可以助力好友来获取资源共享 分站功能 独立后台 会员功能 卡密功能 二级分销功能等 自行研究看 后期有更新新版会在持续发布 目前版本是3.5 是我花三天时间修复的 …