【JS干货分享 | 建议收藏】挑战最短时间带你走进JS(五)

1,236 阅读10分钟

这是我参与 8 月更文挑战的第 16 天,活动详情查看: 8月更文挑战

感激相遇 你好 我是阿ken

作者:请叫我阿ken
链接:juejin.cn/user/109118…
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

🌊🌈关于前言:

文章部分内容及图片出自网络,如有问题请与我本人联系(主页介绍中有公众号)

本博客暂适用于刚刚接触JS以及好久不看想要复习的小伙伴,本文为“JavaScript函数”讲解。

🌊🌈关于内容:

📚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
var num = 10;
// 以下代码由于不存在 var num2, 所以会报错
console.log (num2); // 报错,提示 num2 is not defined(num2 未定义)

运行结果:

在这里插入图片描述

以上代码中 第 2 行在变量 num 声明前就访问了变量 num,却没有像第 5 行的 num2 一样报错,这是因为第 3 行代码中的 var num 会被预解析,例如:

var num;   // num 的变量声明由于预解析而提升到前面
console.log (num); // 输出结果: undefined
num = 10;
// 由于 num的变量声明会被预解析,所以 console.log (num)不会报错,并且由于赋值操作 num = 10 不会被预解析,所以此时 num 的值为 undefined

运行结果:

在这里插入图片描述

预解析能解析 var 变量声明,但不能解析 var 变量声明后面的变量赋值语句

📗4.7.2_预解析_function函数声明

fn();
function fn(){
console.log('fn');  // 该函数最后会被成功调用
}

运行结果:

在这里插入图片描述

以上代码中 fn() 函数调用的代码写在了函数声明的前面,但函数仍然可以正确调用,这是因为 function 函数声明操作会被预解析

再例如:

console.log(fun);
fun(); // 报错,提示fun is not a function (fun 不是一个函数)
var fun = function(){
console.log('fn');
}

运行结果:

在这里插入图片描述

上述代码中 fun 不是一个函数,这是因为 var fun 变量声明会被预解析,预解析后,fun 的值为 undefined,此时的 fun 还不是一个函数,所以无法调用。
只有第 2 ~ 4 行代码执行后,才可以通过 fun() 来调用函数
预解析能解析 函数声明 和 var 变量声明,但不能解析 var 变量声明后的赋值语句

今日入门学习暂时告一段落

Peace

🌊🌈往期回顾:

阿ken的HTML、CSS的入门指南(一)_HTML基础
阿ken的HTML、CSS的入门指南(二)_HTML页面元素和属性
阿ken的HTML、CSS的入门指南(三)_文本样式属性
阿ken的HTML、CSS的入门指南(四)_CSS3选择器
阿ken的HTML、CSS的入门指南(五)_CSS盒子模型
阿ken的HTML、CSS的入门指南(六)_CSS盒子模型
阿ken的HTML、CSS的入门指南(七)_CSS盒子模型
阿ken的HTML、CSS的入门指南(八)_CSS盒子模型
阿ken的HTML、CSS的入门指南(九)_浮动与定位
阿ken的HTML、CSS的入门指南(十)_浮动与定位
阿ken的HTML、CSS的入门指南(十一)_浮动与定位
阿ken的HTML、CSS的入门指南(十二)_表单的应用
阿ken的HTML、CSS的入门指南(十三)_表单的应用
阿ken的HTML、CSS的入门指南(十四)_表单的应用
阿ken的HTML、CSS的入门指南(十五)_表单的应用
阿ken的HTML、CSS的入门指南(十六)_多媒体技术

🌊🌈关于后记:

感谢阅读,希望能对你有所帮助 博文若有瑕疵请在评论区留言或在主页个人介绍中添加联系方式私聊我 感谢每一位小伙伴不吝赐教

原创不易,「点赞」+「关注」 谢谢支持❤