首页 🚓JavaScript

js基础day04

  • [x] 能够通过for循环遍历数组中的数据并打印

    // 正序遍历
    for ( let i = 0 ; i < arr.length ; i++ ) {
        console.log(arr[i]);
    }
    
    // 倒序遍历
    for ( let i = arr.length - 1 ; i >= 0 ; i-- ) {
        console.log(arr[i]);
    }
  • [x] 能够求出一组数中的最大值

    let arr = [298, 1, 3, 4, 6, 2, 2333, 88,77,44];
    
    // 1、先假设第一个数为最大值
    let max = arr[0];
    
    // 2、需要那数组中的每一项与max进行比较——》数组的遍历
    for ( let i = 1 ; i < arr.length ; i++ ) {
        if (max < arr[i]) {
            // 如果发现更大的,此时更新最大值
            max = arr[i];
        }
    }
    
    console.log(max);
  • [x] 能够说出函数的形参和实参的区别

    • 形参:在函数声明的()中的参数,称之为形参
    • 实参:在函数调用的()中的参数,称之为实参
  • [x] 能够使用函数封装一段代码重复使用(用function包裹,比如:求两个任意数字的和)

    function 函数名(形参) {
        函数体
    }
    
    函数名(实参);
  • [x] 能够说出函数中return的作用

    • return:返回值,把函数内部的结果返回给函数外
  • [x] 能够说出函数的三要素

    • 函数名
    • 函数的参数
    • 函数的返回值
  • [x] 能够封装一个函数返回两个数的最大值

    function getMax(num1,num2) {
        let max = num1 > num2 ? num1 : num2;
        return max;
    }
  • [x] 能够说出全局作用域和局部作用域的区别

    • 全局作用域:script标签内,函数外的区域
    • 局部作用域:在函数内的区域
  • [x] 能够书写定义函数的两种不同方式

    // 函数声明式:
    function 函数名(形参){
        函数体
    }
    函数名(实参);
    
    // 函数表达式
    let fn = function () {
        函数体
    }
    fn();

。。。。。。

理解上课的知识点......

数组的案例

  1. 求一组数中的所有数的和跟平均值

    // 1、求一组数中的所有数的和跟平均值
    let arr = [298, 1, 3, 4, 6, 2, 23, 88,77,44];
  1. 求一组数中的最大值

    // 2、求一组数中的最大值
    //     1、先假定第一个数是最大的,用变量max存储
    //  2、拿之后的每一项与max比较,如果发现更大的,此时更新最大值(把max换成这个更大的值)
    //  3、比较到最后max就是最大值
    let arr = [298, 1, 3, 4, 6, 2, 23, 88,77,44];
  1. 求一组数中的最小值和最小值所在的位置

    // 3、求一组数中的最小值和最小值所在的位置
    //  1、先假定第一个数是最小值,用变量min储存,假定最小值位置下标为0,用变量minIndex存储
    //  2、拿之后的每一项与min比较,如果发现更小的,此时更新最小值的同时,把minIndex也更新即可
    let arr = [298, 1, 3, 4, 6, 2, 23, 88,77,44];
---


  1. 要求:反转数组

    // 4、让数组每一项倒序保存另一个数组中去:["a", "bb","ccc","dddd"] ——》 ['dddd','ccc','bb','a'];
    //  1、先把第一个数组倒序遍历
    //  2、把倒序遍历的值存在数组中 newArr.push(arr[i])
    let arr = ["a", "bb","ccc","dddd"];
  1. 要求:将数组中的0去除掉,只将不为0的值存到新数组中去

    // 5、将数组中的0去除掉,只将不为0的值存到新数组中去
    //   1、打印出数组中有除了0以外的数字(打印非0的数字)
    //   2、把非0的数字存到新数组中
    let arr = [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9];
  1. 要求:将数组中的每一项拼接成一个字符串

    // 6、将字符串数组中每一项拼接成一个字符串,并且以|分割:["a", "bb","ccc","dddd"]——》'a|bb|ccc|dddd'
    //  1、遍历数组
    //  2、把每一项拼接字符串
    //  3、在拼串的时候,中间加一个|
    let arr = ["a", "bb","ccc","dddd"];

函数(function)

为什么要学习函数

在写代码的时候,有一些 重复的需求代码需要多次使用 ,如果直接复制粘贴的话,会造成大量的冗余代码。

此时可以利用函数,将一段重复的代码进行封装(一坨代码放在一块)

// 第一天, 讲一遍故事
console.log('从前有座山');
console.log('山里有座庙');
console.log('庙里有个老和尚');
console.log('老和尚给小和尚讲故事');

// 第二天, 讲一遍故事
console.log('从前有座山');
console.log('山里有座庙');
console.log('庙里有个老和尚');
console.log('老和尚给小和尚讲故事');

......
重复的代码(冗余)

函数的好处:实现代码复用,提高开发效率

函数的特点:函数可以一次声明,多次调用!

函数的声明与调用

函数的声明语法:

function 函数名(){
    函数体(需要重复的代码)
}

函数调用的语法:

函数名();

例子

// 声明一个讲故事的函数
function tellStory() {
    console.log('从前有座山');
    console.log('山里有座庙');
    console.log('庙里有个老和尚');
    console.log('老和尚再给小尼姑讲故事');
}
// 调用讲故事的函数
tellStory();

特点:

  • 函数可以把一段重复的代码进行封装
  • 函数一次声明,可以多次调用

    > 类似于录音机录了一次之后,可以播放很多次
    
  • 函数只声明,函数体是不会执行的

    > 类似于录音机录好的音乐,不会自己播放
    

小结:

  1. 函数的声明语法是什么?
  2. 函数的调用语法是什么?

ヾ(๑╹◡╹)ノ" 1、函数声明与调用练习
// 1、封装一个打招呼的函数
// 2、封装一个函数,计算100和200的和
// 3、封装一个函数,计算1~100之间所有数的和

函数的参数

上面写的计算两个数的和存在问题,如果第一次求10+20的和,第二次求100+200的和,此时怎么办?

可以把需要求和的两个数作为参数传到函数里面,函数体中计算参数的和即可:

  1. 形参(形式参数):在函数声明时,设置的参数。作用是占位置。
  2. 实参(实际参数):在函数调用时,传入的参数。作用:函数调用时,会把实参的值赋值给形参,这样形参就有了值。

例子:

function getSum(a,b) {
    console.log(a + b);
}
getSum(10 + 20);
getSum(100 + 200);

形参:

  • 在函数声明时,() 中的参数
  • 形式参数:默认没有具体的值或者类型,只有当调用时,形参才有具体的值或者类型
  • 作用:占位置

实参:

  • 在函数调用时,给函数传递的参数
  • 实际参数:默认有具体的值或者类型
  • 作用:函数调用时,会将实参的值,传递给形参

函数声明与调用的进阶写法:

// 函数声明
function 函数名(形参1, 形参2, 形参3,...){
  函数体;
}
// 函数调用
函数名(实参1, 实参2, 实参3,....);

小结:

  1. 函数的形参指的是什么?

    • 函数声明的()中的参数,称之为:形参
  2. 函数的实参指的是什么?

    • 函数调用的()中的参数,称之为:实参
  3. 规范来说函数的实参和形参个数需要如何?

    • 一一对应

ヾ(๑╹◡╹)ノ" 2、函数参数的练习

函数内部需要变化的值,可以提取成函数的参数

// 1. 封装一个函数,计算1~n之间所有数的和

// 2. 封装一个函数,计算m-n之间所有数的积

// 3. 每位学生不同学科的分数是一个数组,计算每个学生的总分
let zs = [100,100,100];
let ls = [89,92,80];
let ww = [90,80,70];

初学者关键在于熟悉语法,对于复杂的情况之后的课程会不断拓展。

函数的返回值

说明:

  1. 函数是被设计为执行特定任务的代码块
  2. 调用函数的时候不需要管函数内容,只需要一个结果

缺点:之前的写法把计算后的结果处理方式写死了,内部处理完了,使用者要修改还要该源码

解决:把处理结果返回给调用者,这样使用者想怎样处理都行

举例:封装一个买爽歪歪的函数

如果需要函数内部的结果,返回到函数外,让函数外可以正常访问,可以通过设置return返回值做到。

返回值语法:

// 函数的声明
function 函数名(形参1, 形参2, 形参...){  
    函数体;  
    // 函数的返回值,就是函数的结构  
    return 返回值;
}
// 可以在调用时通过变量来接收这个返回值
let 变量 = 函数名(实参1, 实参2, 实参3);
// 此时变量的值等于函数的返回值

注意点:

  • 函数的返回值可以通过一个变量接收,然后对返回值进行之后的操作
  • 其实之前已经接触过函数有返回值的情况了

    // 这些函数都是js底层内置好的,我们直接使用即可
    // 当然,也不是所有函数都有返回值,有的函数则没有返回值,需要根据需求决定
    let age = prompt('请输入您的年龄');
    let num = parseInt('3.1415926');
ヾ(๑╹◡╹)ノ" 3、函数返回值的练习
// 1、封装一个函数,计算任意两个数的和,并且返回结果
// 2、封装一个函数,计算 1~n 之间所有数的和,并且返回结果
// 3、封装一个函数,计算 m~n 之间所有数的积,并且返回结果

函数三要素

  • 函数名: 函数可以一次声明,通过函数名可以做到多次调用(一般命名套路是:动词 + 名词)
  • 函数的参数:可以没有,但是如果函数体内有需要变化的值,此时就需要把变化的量提取出形参
  • 函数的返回值: 可以没有,但是如果需要拿到函数的执行结果,就需要return返回值!!!

开发中:参数和返回值看实际需求决定!

ヾ(๑╹◡╹)ノ" 4、函数三要素的练习
// 1、封装一个函数,求任意2个数中的最大值,返回最大值
// 2、封装一个函数,求任意数字数组中的最大值,返回最大值
// 3、封装一个函数,翻转任意数组,返回翻转之后的新数组

函数的调试

在函数内部是可以继续调用函数的。

function study() {    
    console.log('早上8点,开始学习');        
    // 在study函数的函数体中调用了play函数    
    play();        
    console.log('晚上9点,结束学习');
}
function play() {    
    console.log('早上8点半开始玩手机');    
    console.log('晚上8点半结束玩手机');
}
// 只有在调用时, 浏览器才会执行函数体中的代码
study();

如果需要看上面函数的执行过程,可以通过调试工具调试一下

调试工具

从左往右看:

  • 第一个:瞬间执行到下一个断点处
  • 第二个:让代码往下执行一步(如果遇到函数的调用,瞬间执行完得出结果,不显示过程)
  • 第三个:让代码往下执行一步(如果遇到函数的调用,会进入函数体中显示过程)

    > 想进入函数看里面的代码使用
    
  • 第四个:瞬间执行完当前函数(不显示过程)

    > 不想看函数里面的代码了,可以使用跳出
    

函数的注意点

需求:求两个任意数的和,封装成函数

要求形参与实参需要一一对应!!但是如果在调用是,传实参写少了,或者写多了,是什么情况呢??

函数参数的注意点:

一般形参与实参的个数需要一一对应!

  • 如果参数传少了,没有接收到的值就是undefined(尽量避免这种情况,代码可能会有问题)
  • 如果参数传多了,前面的会一一对应,对于多出的会被忽略

    其实函数内部拥有一个关键字 arguments ,里面装着所有的实参

    function test() {    
        // arguments:函数内部存在一个关键字,将所有的实参储存在里面    
        console.log(arguments);
    }
    test(10,20,30,40,50);

函数返回值的注意点:

一个函数的返回值,指的是函数调用的结果

  • 如果没有设置return,默认返回值是undefined
  • return表示函数返回结果,函数已经结束,return之后的代码就不执行了!

函数名不能重名的注意点:

相同的函数名,写在后面的会覆盖前面的

function fn() {    
    console.log('哈哈哈');
}
function fn() {    
    console.log('嘻嘻嘻');
}
function fn() {    
    console.log('棠哥最帅!');
}
fn();

作用域

变量起作用的区域

问题:

function fn() {  
    let num = 123;  
    console.log(num);// ???
}
fn();
console.log(num);// ???

作用域分类

  1. 局部作用域:函数内部的区域
  2. 全局作用域:在script标签内,函数外部的区域
  3. 块级作用域:let 配合 {} 包裹起来的区域(ES6阶段会讲解,目前了解)

变量分类

局部变量

  • 在函数内部声明的变量,就叫做 局部变量
  • 局部变量,只能在当前函数内部使用!
function fn () {    
    let num = 22;// num是fn函数内部的变量,是局部变量,只能在fn中使用  
    console.log(num);
}
fn();
console.log(num);// 报错

全局变量

  • 在全局作用域中,声明的变量,就叫做全局变量
  • 全局变量 ,在任何地方都可以使用!
let num = 11;
function fn () {    
    console.log(num);// 可以访问全局变量num
}
fn();
console.log(num);// 可以访问全局变量num

全局变量与局部变量的访问规则

下列打印的结果是什么:

先明确是什么变量,再判断值

模拟浏览器的执行

(◕ᴗ◕✿)画图演示

如果自己作用域中有声明这个变量,就用自己的!

let num = 11;
function fn() {  
    let num = 22;  
    console.log(num);
}  
fn();
console.log(num);
(◕ᴗ◕✿)画图演示

如果自己作用域中没有声明这个变量,就用外面的(全局作用域)

let num = 11;
function fn() {  
    num = 22;  
    console.log(num);
}  
fn();
console.log(num);

归纳:自己有就用自己的,自己没有就用外面的!

ヾ(๑╹◡╹)ノ" 5、作用域访问规则练习 (◕ᴗ◕✿)画图演示
let num = 22;
function fn() {    
    console.log(num);
    num = 11;    
    console.log(num);
}
fn();
console.log(num);

拓展:块级作用域(ES6)

let 配合 {} 包裹起来的区域,可以产生块级作用域

  • let配合{}可以产生块级作用域
{
    let a = 10;    
    console.log(a);// 10
}
console.log(a);// i is not defined
  • 早期的var声明不能配合{}产生块级作用域
{    
    var b = 20;    
    console.log(b);// 20
} 
console.log(b);// 20
  • for循环中的let声明注意点
for ( let i = 1 ; i <= 100 ; i++ ) {    
    console.log(i);
}
console.log(i);// i is not defined

定义函数的两种方式

两种方法各有千秋,都有使用的场景

函数声明

function fn() {    
    console.log("呵呵");
}
fn();

函数表达式

let fn = function() {   
    console.log("呵呵");
}
fn();

区别:

  • 函数声明可以先调用,再声明(js代码在执行前,会将所有函数的声明提升到最前面)
  • 函数表达式必须先声明赋值,再调用

匿名函数(了解)

匿名函数:没有名字的函数

场景一:函数表达式

let fn = function (){    
    console.log('呵呵');
}
// 将函数赋值给变量fn,此时函数没有名字

场景二:立即执行函数(匿名函数自调用)(IIFE)

函数可以自调用(声明后立马使用),但是直接调用会报错,此时需要用()把整个函数体包裹起来

// ------------------------------函数自调用
(function fn(){    
    consolo.log('呵呵');
})();
//-------------------------------匿名函数自调用
(function (){    
    consolo.log('呵呵');
})();
  • 注意点:一般匿名函数自调用之间需要加上分号

立即执行函数(匿名函数自调用)的应用(了解)

在多人同时写代码时,如果都使用的是全局变量,很容易与其他人的全局变量互相影响,这叫做全局变量污染

一般使用沙箱模式(匿名函数自调用):每个人的代码在单独的作用域中,不会互相影响

例子:

// 小张写的代码,单独运行没毛病
let a = 11;
console.log(a);
function b() {    
    console.log('bbbb');
}
b();
// 小王写的代码,单独运行没毛病
let b = 22;
console.log(b);
function a() {    
    console.log('aaaa');
}
a();
//---------------------但是如果一起运行,全局变量就会互相影响了(全局变量污染)

解决方法:

  • 只需要让每个人的代码中的变量变成局部变量即可(用函数包裹起来即可)
  • 简写就是函数的自调用,但是有名字的函数还是会全局变量污染,所以使用匿名函数自调用

1、数组遍历的练习

// 1、求出下列数组中所有数的和、最大值、最小值。
let arr = [123,321,233,666,1,7,888,11,23,60,123];

// 2、弹出10次输入框,让用户输入10个数字,把10次的数据储存到数组中,求出10次输入数字中的最大值和最小值,打印出来

// 3、将下列字符串数组中的数据,倒序拼接成一个字符串
let arr = ['aaa','bbb','ccc','ddd','eee'];// 得到'eee-ddd-ccc-bbb-aaa'

2、函数的练习

// 1、封装一个函数,求任意数字数组中的最小值,返回求出的最小值

// 2、封装一个函数,求出任意数组以任意字符串拼接之后的一个字符串,传入数组和分隔符字符串两个参数,返回拼接好的字符串

3、作用域测试

let a = 18;
function fn() {  
    let b = 9;  
    console.log(a);  
    console.log(b);
    b = 10;
}
fn();
console.log(a);
console.log( b );



文章评论

目录