目录
- 引言
- 一、函数基本注意事项
- 1. 函数定义
- 2. 默认参数
- 3. 函数返回值及闭包
- 3.1 举个函数返回值的简单例子
- 3.2 当我需要利用函数内部变量做一些运算时,就需要使用js的闭包
- 二、函数注释
- 1. 单行注释
- 2. 多行注释
- 3. 进阶玩法
- 三、总结
引言
本系列教程旨在帮助一些零基础的玩家快速上手前端开发。基于我自学的经验会删减部分使用频率不高的内容,并不代表这部分内容不重要,只是对于初学者来说没必要一开始就学的面面俱到。我希望可以先通过主干内容带大家入门前端,细节技巧性内容,可以在后续的开发工作中自行发现并掌握。
在上一篇【前端开发入门】JavaScript快速入门–数据操作 中,我们已经熟悉了js基本数据操作,本篇主要介绍js的函数封装。
函数封装也没啥特别的东西,主要是将实现特定功能的js逻辑运算打成一个包,一个入口传参也可以不需要,一个出口返回处理结果也可以不需要。无需关心内部是如何操作的。我会把日常编写函数需要注意的地方列举一下,仅供参考。
一、函数基本注意事项
1. 函数定义
简单过一下函数定义的基本写法
为了避免一些不必要的麻烦,遵循先定义后使用的原则,我比较倾向于后两种写法。
- 第一种写法存在函数提升,可以在定义函数前提前调用,使用起来更加便捷,但是对于项目庞大或者多人协作不太友好(函数定义的位置不好找,但是不影响调用,这会使得出现一些意外的bug)。
- 第二三种写法不存在函数变量提升,强制先定义后调用,颠倒顺序会报错提醒。
// 函数声明
function add(a, b) {return a + b;
}// 函数表达式
const multiply = function(a, b) {return a * b;
};// 箭头函数(ES6)
const subtract = (a, b) => {return a - b;
};
2. 默认参数
当我需要函数没有传入参数时也可以正常运行
写法1:利用 ||
符号给参数赋默认值
// 使用默认参数
const greetWithDefault = (name) => {name = name || "default user";console.log("Hello, " + name + "!");
};
// 调用函数
greetWithDefault(); // 输出: Hello, default user!
greetWithDefault("qbbmnn"); // 输出: Hello, qbbmnn!
写法2:利用es6的函数参数默认值写法
// 使用默认参数
const greetWithDefault = (name = 'default user') => {console.log('Hello, ' + name + '!');
}
// 调用函数
greetWithDefault(); // 输出: Hello, default user!
greetWithDefault('qbbmnn'); // 输出: Hello, qbbmnn!
3. 函数返回值及闭包
函数内部可以使用
return
关键字返回一些内容,此时函数被调用后整体表现为return的内容
需要注意的点:return即代表函数执行完毕的地方,return后边的代码(仍在函数体内部)不会再被执行。
3.1 举个函数返回值的简单例子
const test = () => {const innerVal = 1;return innerVal;
};
// 调用函数,test()此时被替换为innerVal的值,整体作为表达式赋值给res
const res = test();
console.log(res); // 输出:1
3.2 当我需要利用函数内部变量做一些运算时,就需要使用js的闭包
简单的理解闭包:函数返回一个内部函数,内部函数调用了函数内部的变量,使得函数内部变量可以参与到函数外部的运算中去。
const test = () => {const innerVal = 1;const inner = (outerVal = 2) => {// inner函数调用了test函数内部变量console.log(outerVal + innerVal); // 访问外部函数的变量};// 将inner函数返回出去return inner;
};
// 此时res被赋值了inner函数
const res = test();
res(5);// 输出:6
此时我们就完成了js的闭包,虽然这个特性可以让我们利用函数内部的变量完成一些外部调用运算,但是我们仍需注意一下内存管理。
内存管理过程
- 函数调用:调用 test() 函数时,JavaScript 引擎会在栈内存中为 test 函数创建一个新的作用域。
- 变量声明和初始化:在 test 函数的作用域中,声明并初始化了局部变量 innerVal,其值为 1。
- 闭包创建:在 test 函数内部定义了一个名为 inner 的函数,这个函数可以访问 test 函数的作用域中的 innerVal。
- 返回闭包:test 函数返回 inner 函数。
- 赋值给 res:返回的 inner 函数被赋值给 res 变量。
内存保留
- 闭包引用:由于 res 变量引用了 inner 函数,而 inner 函数又引用了 innerVal,因此 innerVal 的内存不会被释放。JavaScript 引擎会保持 innerVal 的内存,以确保 inner 函数在任何时候都能访问到它(假如innerVal占用内存很大,但是res一直没有被调用,那么这块内存将被持续占用,也就是内存泄漏)。
- 当res不再被使用时,我们需要释放res的内存占用,进而释放innerVal的内存占用。
// 断开引用,释放内存
res = null
二、函数注释
注释内容虽然不执行,但是对于我们熟悉代码逻辑有着很大的帮助。
1. 单行注释
常用的注释手法,vscode的快捷键为
Ctrl + ?
- 我们可以在任意行代码的空白处按下快捷键(或是手动敲出两个
\\
符号)添加注释描述内容。 - 遇到暂时不需要但是可能之后有用的代码,我们可以鼠标选中那部分代码,然后按下注释快捷键,直接多行注释。
// 创建计数器函数
const createCounter = () => {let count = 0;return {// 选中多行,直接按下注释快捷键,将代码注释掉// increment: function () {// count++;// return count;// },decrement: function () {count--;return count;},};
};
2. 多行注释
以
/*
开头,*/
结尾,中间可以填任意内容而不被执行
/*
这是一个多行注释的例子
可以包含多行文本
不会被执行的代码都可以放在这里
*/
3. 进阶玩法
这里需要利用一个vscode插件 : koroFileHeader
,可根据需求进行配置:配置文档
插件安装完成后,此时我们鼠标放在函数名那一行(或是函数名上方的空白行)按下快捷键 Ctrl + Shift + ?
即可得到一个模板注释
/*** @description: 执行加法运算的函数* @param {*} a * @param {*} b* @return {*}*/
const add = (a, b) => {return a + b;
};
add(1, 2);
当你鼠标悬浮在add函数调用的地方,vscode会根据你注释的内容给出函数说明提示
我们也可以在注释中加入一些 markdown
语法(只支持部分语法)
总之注释是为了更好的解释你的代码在干什么,不论是对于多年后自己重新审视代码,或是其他人参考你的代码,都会带来极大的便利。
三、总结
本篇我们主要介绍了函数的基本使用技巧,包含函数的默认参数、函数闭包,利用这些特性可以帮助我们优雅的完成代码逻辑编写。此外我详细的列举了注释的几个玩法,感兴趣的朋友可以研究下 koroFileHeader
的配置文档,它不只是可以添加函数注释,还可以添加文件的头部注释等。
再接再厉~