return num2;
}
}
console.log ( getMax(1, 3) ); // 输出结果: 3

或者
function getMax (num1, num2) {
return num1 > num2 ? num1 : num2;
}
console.log ( getMax(1, 3) ); // 输出结果:3

#### 📗4.2.2\_利用函数求任意一个数组中的最大值
回顾一下如何创建数组:
[【熬夜猛肝万字博文】学妹问我怎么入门 Javascript,百般盘问下我终于决定贡献出自己的 JavaScript入门笔记(三)](https://bbs.youkuaiyun.com/topics/618540462)
function getArrMax(arr) {
var max = arr[0];
for(var i = 1; i <= arr.length; i++) {
if(arr[i] > max) {
max = arr[i];
}
}
return max;
}
var arr = getArrMax([5, 2, 99, 101, 67, 77]);
console.log(arr); // 输出结果: 101

或者
function getArrMax(arr){
var max = arr[0];
for(var i = 1; i <= arr.length-1; i++) {
if(arr[i] > max){
max = arr[i];
}
}
return max;
}
console.log( getArrMax( [5, 2, 99, 101, 67, 77]) );
// 输出结果:101

#### 📘4.2.3\_利用 return 提前终止函数
**return 语句之后的代码不会被执行。**
例如:在 getMax() 函数中判断两个参数是否都是数字型,只要其中一个不是数字型,则提前返回 NaN。
function getMax(num1,num2){
if(typeof num1 != ‘number’ || typeof num2 != ‘number’){
return NaN;
}
return num1 > num2 ? num1 : num2;
}
console.log( getMax(1, ‘3’) ); // 输出结果:NaN

>
> **NaN( Not a Number,非数),是计算机科学中数值数据类型的一类值,表示未定义或不可表示的值。**
> **null(空型)、undefined(未定义型)、number(数字型) 为基本数据类型。**
>
>
>
#### 📒4.2.4\_利用 return 返回数组
在函数中使用 return 时,应**注意 return 只能返回一个值**。即使**使用多个逗号隔开多个值,也只有最后一个值被返回。**
function fn(num1, num2){
return num1, num2;
}
console.log( fn(1, 2) ); // 输出结果:2

在开发中,当需要返回多个值的时候,可以用数组来实现,也就是将要返回的多个值写在数组中,作为一个整体来返回。
function getResult(num1, num2){
return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
console.log( getResult(1,2) ); // 输出结果: (4)[ 3, -1, 2, 0.5 ]

### 📚4.3\_函数综合案例
#### 📙4.3.1\_利用函数求所有参数中的最大值
function getMax(){
var max = arguments[0];
for(var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log( getMax(1,2,3) );// 输出结果:3
console.log( getMax(1,2,3,4,5) );// 输出结果:5
console.log( getMax(11,2,34,666,5,100) );// 输出结果:666
#### 📗4.3.2\_利用函数反转数组元素顺序
function reverse(arr){
var newArr = [];
for(var i = arr.length - 1; i >= 0; i–){
newArr[newArr.length] = arr[i];
}
return newArr;
}
var arr1 = reverse( [1, 3, 4, 6, 9] );
console.log(arr1);// 输出结果:(5)[9,6,4,3,1]
#### 📘4.3.3\_利用函数判断闰年
function isLeapYear(year){
var flag = false;
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
flag = true;
}
return flag;
}
console.log( isLeapYear(2020) ? ‘2020是闰年’ : ‘2020不是闰年’ );// 2020是闰年
console.log( isLeapYear(2021) ? ‘2021是闰年’ : ‘2021不是闰年’ );// 2021不是闰年
#### 📒4.3.4\_获取指定年份的2月份的天数
//该题目答案要加上4.3.3的代码
function fn(){
var year = prompt(‘请输入年份’);
if ( isLeapYear(year) ){
alert(‘当前月份是闰年,2月份有29天’)
}else{
alert(‘当前月份是平年,2月份有28天’)
}
}
function isLeapYear(year){
var flag = false;
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
flag = true;
}
return flag;
}
fn();
### 📚4.4\_函数进阶
#### 📙4.4.1\_函数表达式
**函数表达式是将声明的函数赋值给一个变量**,通过变量完成函数的调用和参数的传递。
//函数声明
function funcName() {
// 函数体
}
var sum = function (num1, num2) {
// 函数表达式
return num1 + num2;
};
console.log ( sum(1,2) ); // 3
**函数表达式与函数声明的定义方式几乎相同,不同的是函数表达式的定义必须在调用前,而函数声明的方式则不限制声明与调用的顺序。由于 sum 是一个变量名,给这个变量赋值的函数没有函数名,所以这个函数也叫匿名函数。
将匿名函数赋值给了变量 sum 后,变量 sum 就能像函数一样调用。**
#### 📗4.4.2\_回调函数
项目开发中,若想要函数体中某部分功能由调用者决定,此时可以使用回调函数。**所谓回调函数指的就是一个函数A作为参数传递给一个函数B,然后在B的函数体内调用函数A。**此时,我们**称函数A为回调函数**。其中,匿名函数常用作函数的参数传递,实现回调函数。
function cal(num1,num2,fn){
return fn(num1,num2);
}
console.log( cal(45,55,function(a,b){
return a+b; })
);
console.log(cal(10,20,function(a,b){
return a*b; })
);

>
> **回调函数和递归调用好好理解一下**
>
>
>
#### 📘4.4.3\_递归调用
**递归调用是函数嵌套调用中一种特殊的调用。**
它**指的是一个函数在其他函数体内调用自身的过程,这种函数成为递归函数。**
>
> **递归函数和回调函数的区别,这是你需要思考的**
>
>
>
需要注意的是,递归函数只可在特定的情况下使用,如计算阶乘。
function factorial(n){ //定义回调函数
if( n == 1 ){
return 1;
}
return n * factorial(n - 1);
}
var n = prompt(‘求n的阶乘\n n是大于等于1的正整数,如2表示求2!。’);
n = parseInt(n);
if(isNaN(n)){
console.log(‘输入的n值不合法’);
}else{
console.log(n + ‘的阶乘为:’+factorial(n));
}
>
> **自己想办法搞一搞,对于刚学小白来说,有点难**
>
>
>
### 📚4.5\_作用域
#### 📙4.5.1\_作用域的分类
**变量需要先定义后使用,但声明变量后并不是就可以在任意位置使用该变量。**
function info() {
var age = 18; //此处age为局部变量
}
info();
console.log (age);
//报错,提示age is not defined(age未定义)
//该处只能调用全局变量
从上述代码中可以看出,**变量需要在它的作用范围内才可以被使用,这个作用范围称为变量的作用域。JavaScript 根据作用域使用范围的不同,将其划分为全局作用域、函数作用域和块级作用域**(ES 6提供的)
* **① 全局变量: 不在任何函数内声明的变量都称为全局变量, 它在同一个页面文件中的所有脚本内都可以使用。**
* **② 局部变量: 在函数体内利用 var 关键字定义的变量称为局部变量, 它仅在该函数体内有效。**
* ③ 块级变量: ES 6提供的let 关键字声明的变量称为块级变量, 它仅在该函数体内有效。(理解即可)
#### 📗4.5.2\_全局变量和局部变量
//全局作用域
var num = 10; //全局变量
function fn() {
//局部作用域
var num = 20; //局部变量
console.log (num); //输出局部变量num的值,输出结果:20
}
fn();
console.log (num);
//输出全局变量10的值,输出结果:10
在上述代码中,全局变量num和局部变量num虽然名称相同,但是它们互不影响。
需要注意的是,**函数中的变量如果省略var关键字,它会自动向上级作用域查找变量,一直找到全局作用域为止。**
function fn() {
num2 = 20; // 局部变量
}
fn();
// 如果不调用函数,下面的输出语句会报错
console.log (num2);// 输出结果:20;
从以上可以看出,在全局作用域下,添加或省略var关键字都可以声明全局变量;
**而在函数中,添加var关键字声明的变量是局部变量,省略var关键字时,如果变量在当前作用域下不存在,会自动向上级作用域查找变量。
局部变量只能在函数内部使用,函数的形参也属于局部变量。**
从执行效率来说,全局变量在浏览器关闭页面的时候才会销毁,比较占用内存资源;而局部变量在函数执行完成后就会销毁,比较节约内存资源。
#### 📘4.5.3\_作用域链
当在一个函数内部声明另一个函数时,就会出现函数嵌套的效果。
当函数嵌套时,**内层函数只能在外层函数作用域内执行,在内层函数执行的过程中,若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域。称这种链式的查询关系为作用域链。**
var num = 10;
function fn(){ //外部函数
var num = 20;
function fun(){ //内部函数
console.log(num);//输出结果:20
//如果省略 var num = 20; 则输出结果为10
}
fun();
}
fn();
### 📚4.6\_闭包函数
#### 📙4.6.1\_什么是闭包函数
**所谓"闭包"指的就是有权访问另一函数作用域内变量(局部变量)的函数。**
其主要用途:
① 可以在函数外部读取函数内部的变量。
② 可以让变量的值始终保存在内存中。
注意:由于闭包会使得函数中的变量一直被保存在内存中,内存消耗很大,所以滥用闭包可能会降低程序的处理速度,造成内存消耗等问题。
#### 📗4.6.2\_闭包函数的实现
**常见的闭包函数创建方式就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。**
function fn() {
var times = 0;
var c = function() {
return ++times;
};
return c;
}
var count = fn(); //保存fn()返回的函数,此时count就是一个闭包
//访问测试
console.log( count() ); // 输出结果::1
console.log( count() ); // 输出结果::2
console.log( count() ); // 输出结果::3
console.log( count() ); // 输出结果::4
console.log( count() ); // 输出结果::5
// 闭包函数就会这样一直循环,不会重新定义
>
> **仔细思考:闭包函数到底是什么**
>
>
>
### 📚4.7\_预解析
**JavaScript 代码是由浏览器中的 JavaScript 解析器来运行的,在运行其代码时会进行预解析,即对 var 变量声明和 function 函数声明进行了解析。**
#### 📙4.7.1\_预解析\_var 变量声明
console.log (num); // 输出结果: undefined
一、网安学习成长路线图
网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、网安视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
三、精品网安学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、网络安全源码合集+工具包
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
五、网络安全面试题
最后就是大家最关心的网络安全面试题板块
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!