js基础day04笔记

《部分案例代码下载》

学习目标(全天模式)

  • 能够说出函数的形参和实参的区别
  • 能够使用函数封装一段代码重复使用
  • 能够说出函数中return的作用
  • 能够封装一个函数返回两个数的最大值
  • 能够说出全局作用域和局部作用域的区别
  • 能够说出预解析的过程
  • 能够书写定义函数的两种不同方式
  • 能够自定义创建对象
    。。。。。。

理解上课的知识点……

函数的参数

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

需求:计算两个数的和,封装成一个函数

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

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

例子:

1
2
3
4
5
var getSum(a,b) {
console.log(a + b);
}
getSum(10 + 20);
getSum(100 + 200);

形参:

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

实参:

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

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

1
2
3
4
5
6
// 函数声明
function 函数名(形参1, 形参2, 形参3,...){
函数体;
}
// 函数调用
函数名(实参1, 实参2, 实参3,....);
ヾ(๑╹◡╹)ノ” 函数参数的练习

发生变化的值,都能提取成函数的参数(形参)

1
2
3
// 1. 计算1-n之间所有数的和

// 2. 计算m-n之间所有数的积

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

函数的返回值

当函数执行完的时候,我们希望函数可以返回执行的结果(返回值)。也就是返回值。

此时可以通过在函数中设置一个return返回一个返回值

买一瓶爽歪歪~

返回值语法:

1
2
3
4
5
6
7
8
9
// 函数的声明
function 函数名(形参1, 形参2, 形参...){
函数体;
// 函数的返回值,就是函数的结构
return 返回值;
}

//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3);// 此时变量的值等于函数的返回值

注意点: 函数的返回值可以通过一个变量接收,然后对返回值进行之后的操作

ヾ(๑╹◡╹)ノ” 函数返回值的练习
1
2
// 1. 计算1-n之间所有数的和,并且返回结果
// 2. 封装一个函数返回两个数的最大值
————————

函数三要素

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

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

ヾ(๑╹◡╹)ノ” 函数三要素的练习1
1
2
3
4
5
6
7
// 1. 求任意半径的圆的面积
// 圆的面积 = π(3.14) * r * r

// 2. 求任意半径的圆的周长
// 圆的周长 = π * r * 2

// 3. 求任意2个数中的最大值
ヾ(๑╹◡╹)ノ” 函数三要素的练习2
1
2
3
4
// 1. 求任意数组中的最大值
// 2. 求任意数组中的最小值
// 3. 翻转任意数组,返回一个新的数组
// 4. 对任意数组从小到大排序

函数参数与返回值的说明

需求:封装成函数,求两个任意数的和并且返回结果

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

函数参数的注意点:

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

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

函数返回值的注意点:

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

  • return表示函数返回结果,函数已经结束,return之后的代码就不执行了!!

函数的高级知识

函数内部可以调用函数

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function study() {
console.log('早上8点,开始学习');

// 在study函数的函数体中调用了play函数
play();

console.log('晚上9点,结束学习');
}

function play() {
console.log('早上8点半开始玩手机');
console.log('晚上8点半结束玩手机');
}

// 只有在调用时, 浏览器才会执行函数体中的代码
study();

函数的调试

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

调试工具

从左往右看:

  • 第一个:瞬间执行到下一个断点处

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

  • 第三个:让代码往下执行一步(如果遇到函数的调用,会进入函数体中显示过程)

    想进入函数看里面的代码使用

  • 第四个:瞬间执行完当前函数(不显示过程)

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

————————

作用域

变量起作用的区域

  • 局部作用域:

    • 在函数内部,就是局部作用域
    • 在函数内部声明的变量,就叫做局部变量

    注意点: 局部变量,只能在当前函数内部,使用!!

    1
    2
    3
    4
    5
    6
    function fn () {
    var num = 22;// num是fn函数内部的变量,是局部变量,只能在fn中使用
    console.log(num);
    }
    fn();
    console.log(num);// 报错
  • 全局作用域:

    • 在script标签内,函数外,就是全局作用域
    • 在全局作用域中,声明的变量,就叫做全局变量

    注意点: 全局变量,在任何地方,都可以使用!!

    1
    2
    3
    4
    5
    6
    var num = 11;
    function fn () {
    console.log(num);// 可以访问全局变量num
    }
    fn();
    console.log(num);// 可以访问全局变量num

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

下列打印的结果是什么:

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

模拟浏览器的执行

(◕ᴗ◕✿)画图演示
1
2
3
4
5
6
7
var num = 11;
function fn() {
var num = 22;
console.log(num);
}
fn();
console.log(num);
  • 如果自己作用域中有声明这个变量,就用自己的!
(◕ᴗ◕✿)画图演示
1
2
3
4
5
6
7
var num = 11;
function fn() {
num = 22;
console.log(num);
}
fn();
console.log(num);
  • 如果自己作用域中没有声明这个变量,就用外面的(全局作用域)

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

ヾ(๑╹◡╹)ノ” 作用域访问规则练习 (◕ᴗ◕✿)画图演示
1
2
3
4
5
6
7
8
var num = 22;
function fn() {
console.log(num);
num = 11;
console.log(num);
}
fn();
console.log(num);

隐式全局变量

开发中避免出现(一般只会在面试题中提问)

问题:

1
2
num = 10;
console.log(num);// 当前作用域中没有声明,但是已经是全局作用域了没有上一级了,此时浏览器会隐式的去把该变量声明成全局变量
  • 一个变量如果从头到尾没有使用var声明,直接赋值,浏览器会默认变成全局变量——》隐式全局变量
(◕ᴗ◕✿)画图演示
1
2
3
4
5
6
function fn (){
num = 10;
console.log( num );
}
fn();
console.log(num);
ヾ(๑╹◡╹)ノ” 隐式全局变量的小练习
1
2
3
4
5
6
7
var num = 20;
function fn() {
num = 30;// 这个num是隐式全局变量吗?
console.log(num);
}
fn();
console.log(num);

隐式全局变量开发中避免!!!

————————

预解析

预解析:预先解析代码

在代码开始执行之前,都会把变量和函数的声明进行提升!!——》预解析

可以看做浏览器预先想要知道,有哪些变量和函数~

js代码的执行步骤(两步)

  1. 预解析(把变量和函数的声明提升到最前面)

    预先解析代码,把所有变量和函数的声明都会提升(浏览器想要预先知道有哪些变量和函数)

  2. 再一行一行执行代码

问题:

1
2
3
console.log(num);// 讲道理此时还没有声明变量,应该会报错
var num = 12;
console.log(num);

注意点:

  • 所有的变量的声明,都会提升到最顶部,但是不会提升赋值!!!
(◕ᴗ◕✿)画图演示
1
2
3
4
5
// 第一步不是执行代码,而是预解析
console.log(num);
//----------------------------
var num = 12;
console.log(num);
  • 所有的函数的声明,都会提升到最顶部,但是不会提升函数的调用

    1
    2
    3
    4
    5
    6
    // 第一步不是执行代码,而是预解析
    console.log("我是第一行代码");
    fn();
    function fn() {
    console.log('嘻嘻');
    }

以下都是错误的写法

  • 如果同时声明了多个同名的变量,只会提升第一个声明,后面的声明会忽略

    1
    2
    3
    4
    var num = 11;
    var num = 22;
    var num = 33;
    var num = 44
  • 如果同时声明了多个同名的函数,后面的函数声明会覆盖前面的!!(最后只剩一个函数声明)

    开发时避免同名!!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    fn();
    function fn() {
    console.log('呵呵');
    }
    fn();
    function fn() {
    console.log('哈哈');
    }
    fn();
    function fn() {
    console.log('嘻嘻');
    }
    fn();
  • 如果同时声明了同名的变量和函数,函数声明优先!!

    开发中必须避免!!

    1
    2
    3
    4
    5
    6
    console.log(a);
    function a() {
    console.log('我是函数');
    }
    var a;
    console.log(a)
(◕ᴗ◕✿)画图演示

一定要避免这种情况,否则会有bug

1
2
3
4
5
6
var a = 11;
console.log(a);
function a() {
console.log('嘿嘿嘿');
}
a();
ヾ(๑╹◡╹)ノ” 小练习
1
2
3
4
5
6
7
8
9
10
11
//1、getCool() 比比谁最帅!!
// 1、声明多个cool的函数
// 2、不管在哪里调用,结果都是最后一个

//2、
console.log(a);
function a() {
console.log("呵呵呵");
}
var a = 1;
console.log(a);

代码规范:

  • 一般先声明,后使用
  • 不要让函数名与变量名同名!!
ヾ(๑╹◡╹)ノ” 面试题

一般预解析的题目只在面试中会遇到,实际开发中避免

注意点:每个作用域中都有预解析(局部作用域中也有!)

(◕ᴗ◕✿)画图演示
1
2
3
4
5
6
7
8
//1、 每个作用域中都有预解析——》函数内部也会预解析
var num = 10;
fn1();
function fn1() {
console.log(num);
var num = 20;
}
console.log(num);
1
2
3
4
5
6
7
8
//2. 
var a = 18;
fn2();
function fn2() {
var b = 9;
console.log(a);
console.log(b);
}
————————
(◕ᴗ◕✿)画图演示
1
2
3
4
5
6
7
8
9
10
11
12
//3.
fn3();
console.log(c);
console.log(b);
console.log(a);
function fn3() {
a = b = c = 9;// 相当于: a = 9,b = 9,c = 9
// var a = b = c = 9; // 相当于只声明了一个a var a = 9 ; b = 9 ; c = 9;
console.log(a);
console.log(b);
console.log(c);
}

定义函数的两种方式

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

函数声明

1
2
3
4
5
6
7
8
function 函数名(){
//函数体
}
//------------------------------
function fn() {
console.log("呵呵");
}
fn();

函数表达式

1
2
3
4
5
6
7
8
var 函数名 = function(){
//函数体
}
//------------------------------
var fn = function() {
console.log("呵呵");
}
fn();

区别:

  • 函数声明可以先调用,再声明(因为预解析)
  • 函数表达式必须先声明赋值,再调用(相当于变量赋值,只会提升变量声明,不会提升赋值)

匿名函数

匿名函数:没有名字的函数——》不能直接使用,有两个使用场景

场景一:函数表达式

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

场景二:匿名函数自调用——》自执行——》自己调用自己

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

1
2
3
4
5
6
7
(function fn(){
consolo.log('呵呵');
})();
//-----------------------------------
(function (){
consolo.log('呵呵');
})();
  • 注意点:一般规范匿名函数自调用之后需要加上分号

匿名函数自调用的应用(沙箱模式)

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

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

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 小张写的代码,单独运行没毛病
var a = 11;
console.log(a);

function b() {
console.log('bbbb');
}
b();

// 小王写的代码,单独运行没毛病
var b = 22;
console.log(b);

function a() {
console.log('aaaa');
}
a();

//---------------------但是如果一起运行,全局变量就会互相影响了(全局变量污染)

解决方法:

  • 只需要让每个人的代码中的变量变成局部变量即可

    js中只有函数里面才有局部作用域,只需要那函数包裹起来调用即可

  • 简写就是函数的自调用,但是有名字的函数还是会全局变量污染,所以使用匿名函数自调用

————————

对象

为什么学习对象?

为什么要学习数组:数组可以存储大量的数据,并且数组规范一般储存的是同类型的数据!!

对象:万物皆对象,在现实生活中,只要能被描述出来的就是对象

思考:如果需要在js中描述出一个人这个对象,怎么做?

描述人这个对象:

  • 特征:姓名、年龄、性别、身高、体重……
  • 行为:吃饭、睡觉、敲代码……

解决方案:

  • 单独使用变量一个个存——》代码麻烦,需要多个变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // -------------------特征
    var name = "张三";
    var age = 18;
    var sex = "男";
    var height = 180;
    var weight = 150
    // -------------------行为
    var eat = function () {
    console.log('吃饭');
    }
    var sleep = function () {
    console.log('睡觉');
    }
    //-------------------变量太多麻烦
  • 使用数组存——》数组规范一般储存同类型的数据,并且数组中的数据用户不明白分别表示什么意思

    1
    2
    var arr = ['张三',18,'男',180,150];
    //-----------------------数组一般只存储同类型的数据,并且这样写每一项不明确表示什么含义
  • 如果需要描述现实中的对象,此时就需要通过js中的对象完成!

对象的基本概念

数组: 一组有序的值的集合——》下标有序

对象: 一组无序的键值对的集合——》可以用于描述生活中对象的特征与行为

键值对就是类似于之前css中的样式

格式:键:值——》key:value

创建对象的方法

  • 字面量(用的最多)

    123、’abc’、true、undefined、null、[]、{}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var obj = {};// 创建一个空对象
    console.log(obj);
    //----------------------------
    var obj = {
    // ------------特征——》对象的属性
    name:"张三",
    age:18,
    sex:"男",
    height:180,
    weight:150,
    // ------------行为——》对象的方法(对象中的函数)
    eat:function (){
    console.log('吃饭');
    },
    sleep:function (){
    console.log('睡觉');
    }
    };
    console.log(obj);

    注意点:

    • 键值对之间以逗号隔开!!!
    • 对象中的特征叫做对象的属性
    • 对象中的行为(函数)叫做对象的方法
  • 构造函数(用的较少)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var person = new Object();//创建一个空的对象
    //------------------------------
    var person = new Object({
    name:"张三",
    age:18,
    sex:"男",
    height:180,
    weight:150,
    eat:function (){
    console.log('吃饭');
    },
    sleep:function (){
    console.log('睡觉');
    }
    })