函数的概念
- 什么是函数?
- 首先明确一点,和我们数学中的函数是两个概念
- 在 JS 中,函数可以理解为将一段在程序中多次出现的代码封装起来的盒子,以便在多个地方调用执行
- 换句话说:函数就是一个内部封装了部分代码的盒子,可以在多个位置被调用
- 函数的使用
- 创建函数(定义函数)
- 调用函数
简单理解:
函数 * 有一点类似与变量, 因为都是一个盒子, 但是完全不同 * 变量这个盒子内部存放某一个具体的值, 比如: 100, 'QF001', 'qwe' * 函数这个盒子内部不是为了存放某一个具体的值, 而是为了存放某一段需要重复多次出现的 代码 * 现在有一段 多次重复出现的代码, 假设就是 '100万' * 每次使用的时候都需要书写一遍这个大量的代码, 极其不方便, 而且代码量特别多 * 所以我们可以将 '100万' 存储到一个银行卡(函数)中 * 将来需要使用的时候 直接从 银行卡(函数) 中 拿 就行了
函数的定义
- 声明式定义
function fn() {
}
定义(创建)
语法1: function 函数名(参数: 是形参非必传,) { 函数被调用的时候需要执行的某一段代码 }
* 分析:
* function:声明函数的关键字,代表接下来这段代码是一个函数
* fn:函数名,调用函数时需要使用,函数名自定义,符合命名规范和见名知意即可(!** 匿名函数时可以不写)
* ():小括号内存放函数的参数(后续讲解)
* {}:存放函数代码,调用函数时,想执行的代码都写在内部
*/
- 赋值式定义
var fn = function () {
}
两种函数的写法
语法1:
function 函数名 () {} -> 声明式定义
写法1:
function fn1() {
console.log('我是 fn1 函数, 我被调用了')
}
调用:
fn1()
语法2:
var 函数名 = function (参数: 非必传, 暂时不写) {} -> 赋值式定义
写法2:
var fn2 = function () {
console.log('我是 fn2 函数, 我被调用了')
}
调用:
fn2()
总结
定义(创建) 语法1: function 函数名(参数: 是形参非必传,) { 函数被调用的时候需要执行的某一段代码 }
调用(使用)函数名()
注意: 如果一个函数只定义, 而不调用, 那么永远不会执行
函数的参数
什么是参数
- 参数是什么?
- 如果没有参数,那么函数的执行功能是固定的,写好函数后内部内容将不会变
- 比如:函数内部的代码为 1 + 1,那么始终执行时始终都是 1 + 1,如果此时想要计算 1 + 2 的值,需要重新封装一个 1+2 的函数
- 参数在哪里?如何使用
- 书写函数时有一个 () 内部就是书写参数的,函数分为两种,形参---实参
- 形参和实参的区别
- 形参:在函数声明时 function 后边的()内书写,每写一个参数,就相当于在函数内部创建一个变量,其值为函数调用时传递的值,只能在函数内部使用,不能在外部使用
- 实参:顾名思义,实际的参数,也就是函数在调用时传递的参数
function num () {
console.log(1 + 1)
}
num() // 打印值为 1+1
function num (a, b) { // 此处 a b 为形参
console.log(a + b)
}
num(1, 1) // 此处为 实参,分别传递给 a 和 b // 此处打印值为 1 + 2
num(1, 2) //详细解释: 调用 fn 函数的时候, 书写了两个 实参 就是 1和2,
//然后 会按照规则 传递给对应的 形参 就是 形参 a和b,
//那么也就相当于 在 fn 函数中 创建了 一个 变量 并 赋值为 1和2
//这样的好处时 函数中 的形参a, 值不固定, 那么函数的功能也就更加灵活
- 注意
- 函数的形参与实参是按照从左到右的顺序一一对应的
- fn(100, 200, 300)--->调用 fn 函数的时候, 书写了 三个 实参 分别是 100 200 300
- 然后会按照规则 传递给 对应的 形参 (按照书写的顺序)
- 第一个实参 -> 第一个形参
- 第二个实参 -> 第二个形参
- 以此类推
- 所以上述中
-
a === 100 -
b === 200 -
c === 300
-
形参与实参
// 少传参数----实参少, 形参多
//第一个实参会按照顺序给第一个形参, 并以此类推
* 但是 多写的 形参没有对应的实参传递具体的值
* 所以相当于 变量定义了但没有赋值, 所以他们的值都是 undefined
function num1(a, b, c, d) {
console.log(a,b,c,d)
}
num1(1, 2, 3, 4) // 打印1,2,3,4
num1(1, 2, 4) // 打印1,2,4,undefined
num1(4) // 打印4,undefined,undefined,undefined
// 多传参数----实参多, 形参少
//第一个实参会按照顺序给第一个形参, 并以此类推
*多写的实参, 没有对应的形参接收, 那么在函数中暂时无法使用
function num2 (a) {
console.log(a)
}
num2(1, 2) // 打印 1
num2(1) // 打印 1
总结
* 为什么要有参数?
* 为了 让函数的功能 更加灵活, 不会导致函数的功能太过于死板
* 1. 形参
* 函数定义时小括号中书写的内容, 相当于在函数中 创建了一个变量
* 具体的值 有实参提供, 如果 实参没有传递对应的内容, 那么值为 undefined
*
* 2. 实参
* 函数调用时小括号中书写的内容, 这里书写的内容, 会传递给对应的形参
*
* 注意:
* 一个函数可以接收多个形参与实参, 多个形参与实参使用 , 间隔
*
* 虽然形参和实参的数量没有限制, 但是如果太多会导致代码难以阅读, 所以不推荐多写
*
*
* 形参和实参的数量可以不一致 (非常不推荐)
*
*
* 函数中 参数可以具有默认值 (ES6 的新写法)
* 如果一个 函数的参数给了 默认值, 那么这个参数永远不会是 undefined
ES6新写法---可以修改默认值
案例分析
函数的返回值
- 返回值是什么?有什么作用
- 函数内部默认有一个 return 他的值就是函数的返回值,如果函数内部不写 return 那么函数默认在函数体内部最底部返回一个 undefined
- 如果不想返回 undefined 需要手动在函数内部写上 return 并且跟上需要返回的值
- 可以中断函数(后续通过代码演示)
function num (a, b) {
a+b
}
var ab = num(1,2)
console.log(ab)
function num (a, b) {
// return a + b
console.log('函数内部执行的 a + b =',a+b)
}
var ab = num(1,2)
console.log('函数外部执行的 a + b =',ab)
函数的返回值
- 每一个函数调用完毕后 都会有一个结果(值), 默认为 undefined
function fn () {}
// 将 fn 函数的 执行/调用 结果, 存到一个变量 res 中
// 调用写法1:
var res = fn()
console.log(res) // undefined
// 调用写法2:
console.log(fn()) // undefined
- 如果想要更改那么我们需要借助一个 关键字 return
- return 的后边可以跟 任何的数据, 包括表达式
return a + b //这是表达式
return a //这是数据
- 注意:
- 函数中 return 只会生效一个, 因为 return 具有中断函数的能力
function fn () {
return '书写你要返回的内容' // 函数中 return 只会生效一个
return 1 + 1 // 这里函数中 第二个return 不会生效
}
console.log(fn())
- 所以一般 return 会写在函数的末尾,因为 return 具有中断函数的能力,写在中间下面的代码将不会继续执行
// return 具有中断函数的能力
function fn() {
console.log(1)
console.log(2)
return '你好, 你看还会不会打印'
console.log(3)
}
fn()
- 如果想要写在函数的 开头, 必须结合 分支语句
// return 结合 分支语句
function fn (bo) {
// 当我传递参数为 true 正常执行函数功能, 否则, 不执行
if (bo === false) return
console.log('函数的功能正常执行')
}
fn(false)
// fn(true)
- return 不具备 打印的功能, 如果你想看在控制台看到数据, 请书写 console
function fn(a, b) {
// console.log(a + b)
// return 不具备 打印的功能, 如果你想看在控制台看到数据, 请书写 console
return a + b
}
console.log(fn(1,2))
return 案例
// 封装一个函数, 计算出两个数字的最大公约数
/**
* 逻辑:
* 书写一个函数
* 需要两个参数
* 需要返回值, 返回最大的公约数
*/
// 基本版
// function fn(x, y) {
// var min = x > y ? y : x
// var num = 0 // 用于存储最大公约数
// // 拿到 1~较小值 之间的所有数字
// for (var i = min; i >= 1; i--) {
// // 寻找 x 和 y 的公约数
// if (x % i === 0 && y % i === 0) {
// // console.log(i)
// // 当 num 的值 小于 i 的时候, 将 i 的存储到 num, 因为我们要找的是 最大公约数
// if (num < i) {
// num = i
// }
// }
// }
// // return '最大公约数'
// return num
// }
// function fn(x, y) {
// var min = x > y ? y : x
// // 拿到 1~较小值 之间的所有数字
// for (var i = min; i >= 1; i--) {
// // 寻找 x 和 y 的公约数
// if (x % i === 0 && y % i === 0) {
// // console.log(i)
// /**
// * 当前 分支语句执行的时候, 代表找到了 公约数
// * 顺序中 第一个就是最大公约数, 所以当前分支第一次执行完毕后, 就等于找到了最大公约数
// *
// * 然后直接 return i 将最大公约数返回给外部, 并且函数到此结束, 后续不在运行
// */
// return i
// }
// }
// }
// 封装一个函数, 用于判断一个 数字是不是质数
/**
* 逻辑:
* 1. 封装一个函数
* 2. 需要一个参数
* 3. 需要返回值, 并且是布尔值
*/
function fn(n) {
var num = 0 // 用于作为一个计数器
// 1. 找到 2~n-1 之间的所有数字
for (var i = 2; i < n; i++) {
// 2. 找有没有能够和 形参n 完整整除的数字
if (n % i === 0) {
// 3. 当分支执行的时候, 修改 num 的值 (修改计数器)
num++
}
}
// if (num === 0) {
// // 是质数
// return true
// } else {
// // 不是质数
// return false
// }
return num === 0
}
var res = fn(11)
console.log(res)
简单了解对象
- 什么是对象
- 首先排除男女朋友, 我们这是正经编程
- 对象是一个 复杂数据类型, 也叫做 引用数据类型
- 虽然我们说是复杂类型, 但是也没有很复杂, 只不过是存储了一些基本数据类型的集合
var obj = {
num: 100,
str: "hello",
boo: true,
};
- 这里的 {} 和函数中的 {} 不一样, 函数内部书写代码, 对象里面是书写数据的
- 对象就是一个键值对的集合
- 什么是键值对?
- 对象 obj 中, num 是键, 100 是值
- 对象 obj 中, str 是键, 'hello' 是值
- 对象 obj 中, boo 是键, true 是值
- 其实就是我们准备一个房子, 把我们想要的数据放进去, 然后把房子的地址给到变量名, 当我们需要某一个数据的时候, 就可以根据变量名里面存储的地址找到对应的房子, 然后去房子里面找到对应的数据
- 什么是键值对?
创建对象
- 字面量方式创建对象
- 语法:
var obj1 = {键值对, 键值对}
- 语法:
- 内置构造函数创建
- 语法:
var obj = new Object()
- 语法:
- 对象内对于 键(key) 的要求
- 推荐使用符合变量命名规则和规范的名字
- 可以使用纯数字当作 键名
- 这种情况下该属性会排列在最前面
- 可以使用任何特殊符号
- 使用特殊符号的时候,在书写时需要被引号包裹
对象数据类型的操作(增删改查)两种语法
- 点语法
var obj = {}; obj.name = "qianfeng"; // 增 obj.name = "qianfeng123"; // 改 console.log(obj.name); // 查 delete obj.name; // 删 - 中括号语法(数组语法)
var obj = {}; obj["name"] = "qianfeng"; // 增 obj["name"] = "qianfeng123123"; // 改 console.log(obj["name"]); // 查 delete obj["name"]; // 删 - 两者的差异
- 符合变量命名规范与规则的情况,两者并无差异
- 操作不符合变量命名规范与规则的名称时,比如纯数字或者带有特殊符号的,就只能用中括号语法
- 涉及变量相关的时候,只能使用中括号语法
var obj = {
name: '小花',
id: 123456,
age:18,
school:'大学',
sex:'女'
}
console.log('我是之前的' , obj)
// 增
obj['class']= 123;
// obj.class = 123
console.log('我是之后的' , obj)
// 删
delete obj ['sex'];
// delete obj. sex
console.log('我是之后的' , obj)
// // 改
obj ['name']= '美女';
// obj.name = '美女'
console.log('我是之后的' , obj)
// // 查
console.log(obj['name'])
// console.log(obj.name)
console.log('我是之后的' , obj)
注意:浏览器查看的时候是按照26英文字母排序的里面的键值对是位置会有所改变,里面的值是不会变的,更改后的需要在展开里面查看浏览器会自动加载最新的数据但是不会在之前的数据中显示,一定一定要展开看
面试题
- 面试题: JS 中声明变量的三种方式有什么区别?
- var
- let
- const
-
1:变量提升:var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined
let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错 -
2:块级作用域:var不存在块级作用域 、let和const存在块级作用域
-
3:重复声明:var允许重复声明变量 、let和const在同一作用域不允许重复声明变量
-
4:修改声明的变量:var和let可以 const声明一个只读的常量。一旦声明,常量的值就不能改变,但对于对象和数据这种引用类型,内存地址不能修改,可以修改里面的值。