【熬夜猛肝万字博文】学妹问我怎么入门 Javascript,百般盘问下我终于决定贡献出自己的 JavaScript入门笔记(四)

86 篇文章 0 订阅

感激相遇,你好,我是阿ken??

版权声明:本文为CSDN博主「」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
另外,博文中某些图片或内容可能出自网络,如有侵权或问题,请及时私信我

有学妹想以后做前端,就会问到 JavaScript怎么学的问题,在多次百般盘问下,阿ken?? 决定贡献出自己之前学习 JavaScript时的笔记。



安全感这个东西对于大多数人而言
是靠很多次坚持不懈去努力争取的

不要因为没怎么努力过
到头来连一件值得回忆的事情都没有

这不是为了向别人证明自己了不起
这只不过是把本该属于自己的东西夺回来

???

传送门biu~

??4.1_初识函数

??4.1.1_函数的使用

function 函数名() {
//函数体代码
}

function 是声明函数的关键字,必须全部使用小写字母

当函数声明后,里面的代码不会执行,只有调用函数的时候才会执行。
调用函数的语法为“函数名( )”。

案例:

//声明函数
function sayHello() {
console.log ('Hello');
}

//调用函数
sayHello();

在这里插入图片描述

??4.1.2_函数的参数

函数的参数分为形参和实参。

在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参。

当函数调用的时候,同样也需要传递相应的参数,这些参数称为实参。

函数的形参是形式上的参数,因为当函数声明的时候,这个函数还没有被调用,这些参数具体会传过来什么样的值是不确定的。而实参是实际上的参数,在函数被调用的时候。它的值就被确定下来了。

案例:

function 函数名 (形参1, 形参2, ...) {
// 函数体代码
}

函数名 (实参1, 实参2, ...);

JavaScript 函数参数的使用非常灵活,它允许函数的形参和实参个数不同。当实参数量多于形参数量时,函数可以正常执行,多余的实参由于没有形参接收,会被忽略,除非用其他方式(例如后面学到的 arguments )才能获得多余的实参。当实参数量小于形参数量时,多出来的形参类似一个已声明未赋值的变量,其值为 undefined。

function getSum (num1, num2) {
console.log (num1, num2);
}
getSum (1, 2, 3); // 实参数量大于形参数量,输出结果为 1,2
getSum (1); // 实参数量小于形参数量,输出结果为 1,undefined

在这里插入图片描述

??4.1.3_函数的返回值

例如,一个人去餐厅吃饭,我们将餐厅的厨师看成一个函数,顾客通过函数的参数来告诉厨师要做什么菜。当厨师将饭菜做好以后,这个饭菜最终应该是传给顾客。但我们在前面编写的函数都是直接将结果输出,这就像厨师自己把饭菜吃了,没有将函数的执行结果返回给调用者。

格式:

function 函数名() {
return 要返回的值;  //利用 return 返回一个值给调用者
}

案例:

function getResult() {
return 666;
}

// 通过变量接收返回值
var result = getResult();
console.log (result);   // 输出结果:666
// 直接将函数的返回值输出
console.log ( getResult() );// 输出结果:666

console.log (getResult);// 输出结果:输出函数(见下图)

在这里插入图片描述

反例:

function getResult() {
console.log (1);
// 该函数没有return
}

getResult(); // 输出结果: 1
console.log ( getResult() ); // 输出结果: 1 undefined

在这里插入图片描述

??4.2_函数返回值案例

??4.2.1_利用函数求任意两个数的最大值

function getMax (num1, num2) {

if (num1 > num2) {
return num1;
} else {
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入门笔记(三)

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是大于等于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 变量声明后的赋值语句

阿ken??在此求观众老爷来个三连支持一下!!!


如果你还想继续跟阿ken??学习 JavaScript 的话,请看下文:

【熬夜猛肝万字博文】学妹问我怎么入门 Javascript,百般盘问下我终于决定贡献出自己的 JavaScript入门笔记(一)
【熬夜猛肝万字博文】学妹问我怎么入门 Javascript,百般盘问下我终于决定贡献出自己的 JavaScript入门笔记(二)
【熬夜猛肝万字博文】学妹问我怎么入门 Javascript,百般盘问下我终于决定贡献出自己的 JavaScript入门笔记(三)

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值