寒假集训
七十三、函数的概念
- 对于js来说,函数就是把任意一段代码放在一个盒子里面
- 在我想要让这段代码执行的时候,直接执行这个盒子里面的代码就行
- 先看一段代码
//这个是我们以前写的一段代码
for(vari=0;i<10;i++){
console. 1og(i)
}
//函数,这个{}就是那个“盒子”
function fn() {
//这个函数我们以前写的代码
for(vari=0;i<10;i++){
console. 1og(i)
}
}
1.函数定义阶段。
- 定义阶段就是我们把代码放在盒子里面
- 我们就要学习怎么放进去,也就是书写一个函数
- 我们有两种定义方式声明式和赋值式
声明式
- 使用function这个关键字来声明一个函数
- 语法:
function fn(){
//一段代码
}
// function: 声明函数的关键字,表示接下来是一个函数了
// fn:函数的名字,我们自己定义的(遵循变量名的命名规则和命名规范)
// (): 必须写,是用来放参数的位置(一会我们再聊)
// {}:就是我们用来放一段代码的位置 (也就是我们刚才说的“盒子”)
赋值式
- 其实就是和我们使用var关键字是一 个道理了
- 首先使用 var定义一个变量, 把一个函数当作值直接赋值给这个变量就可以了
- 语法:
var fn = functTion () {
//一段代码
}
//不需要在function后面书写函数的名字了,因为在前面已经有了
2.函数调用阶段
- 就是让盒子里面的代码执行一下
- 让函数执行
- 两种定义函数的方式不同,但是调用函数的方式都是一样的
调用一个函数
- 函数调用就是直接写函数名()就可以了
//声明式函数
function fn() {
console.1og('我是fn函数')
}
//调用函数
fn()
//赋值式函数
var fn2 = function () {
console.1og('我是fn2函数')
}
// 调用函数
fn()
- 注意:定义完一个函数以后,如果没有函数调用,那么写在{}里面的代码没有意义,只有调用以后才会执行
3.调用上的区别
- 虽然两种定义方式的调用都是一样的,但是还是有一些区别的
- 声明式函数:调用可以在定义之前或者定义之后
//可以调用
fn()
//声明式函数
function fn() {
console.1og('我是fn函数')
}
//可以调用
fn()
- 赋值式函数:调用只能在定义之后
//会报错
fn()
//赋值式函数
var fn = function () {
console.1og('我是fn函数')
}
//可以调用
fn()
4.函数的参数
- 我们在定义函数和调用函数的时候都出现过(),
- 现在我们就来说一 下这个()的作用
- 就是用来放参数的位置
- 参数分为两种 形参 和 实参
//声明式
function fn(行参写在这里) {
// 一段代码
}
fn(实参写在这里)
//賦值式函数
var fn = function (行参写在这里) {
//一段代码
}
fn(实参写在这里)
5.返回值
- 函数调用本身也是一个表达式, 表达式就应该有一个值出现
- 现在的函数执行完毕之后,是不会有结果出现的
//比如1+2是一个表达式,那么这个表达式的结果就是3
console.1og(1 + 2) // 3
function fn() {
//执行代码
}
//fn()也是一个表达式,这个表达式就没有结果出现
console. log(fn()) // undefined
- return 关键字就是可以给函数执行完毕一个结果
function fn() {
//执行代码
return 100
}
//此时,fn() 这个表达式执行完毕之后就有结果出现了
console. log(fnO) // 100
- 我们可以在函数内部使用return 关键把任何内容当作这个函数运行后的结果
6.预解析
- 预解析其实就是聊聊js代码的编译和执行
- js是一个解释型语言,就是在代码执行之前,先对代码进行通读和解释,然后在执行代码
- 也就是说,我们的js代码在运行的时候,会经历两个环节解释代码和执行代码
解释代码
- 因为是在所有代码执行之前进行解释,所以叫做预解析(预解释)
- 需要解释的内容有两个
声明式函数
- 在内存中先声明有一个变量名是函数名,并且这个名字代表的内容是一个函数
var关键字
- 在内存中先声明有一个变量名
7.作用域
- 什么是作用域,就是一个变量可以生效的范围
- 变量不是在所有地方都可以使用的,而这个变量的使用范围就是作用域
全局作用域
- 全局作用域是最大的作用域
- 在全局作用域中定义的变量可以在任何地方使用
- 页面打开的时候, 浏览器会自动给我们生成一个全局作用域window
- 这个作用域会一直存在,直到页面关闭就销毁了
//下面两个变量都是存在在全局作用域下面的,都是可以在任意地方使用的
var num = 100
var num2 = 200
局部作用域
- 局部作用域就是在全局作用域下面有开辟出来的一个相对小一些的作用域,
- 在局部作用域中定义的变量只能在这个局部作用域内部使用
- 在JS中只有函数能生成一个局部作用域,别的都不行
- 每一个函数,都是一个局部作用域
//这个num是一个全局作用域下的变量在任何地方都可以使用
var num = 100
function fn() {
//下面这个变量就是一个fn局部作用域内部的变量
//只能在fn函数内部使用
var num2 = 200
}
fn()
8.变量使用规则
- 有了作用域以后,变量就有了使用范围,也就有了使用规则
- 变量使用规则分为两种,访问规则和赋值规则
访问规则
- 当我想获取一个变量的值的时候,我们管这个行为叫做访问
- 获取变量的规则:
首先,在自己的作用域内部查找,如果有,就直接拿来使用
如果没有,就去上一级作用域查找,如果有,就拿来使用
如果没有,就继续去上一级作用域查找,依次类推
如果一直到全局作用域都没有这个变量,那么就会直接报错(该变量is not defined)
var num = 100
function fn() {
var num2 = 200
function fun() {
var num3 = 300
console. 1og(num3) //自己作用域内有,拿过来用
console. 1og(num2) //自己作用域内没有,就去上一级,就是fn的作用域里面找,发现有,拿过来用
console. 1og(num) // 自己这没有,去上一级fn那里也没有,再上一级到全局作用域,发现有,直接用
console.1og(a) //自己没有,一级一级找上去到全局都没有,就会报错
}
fun()
}
fn()
- 变量的访问规则也叫做作用域的查找机制
- 作用域的查找机制只能是向上找,不能向下找
function fn(){
var num=100
}
fn()
console.log(num)//发现自己作用域没有,自己就是全局作用域,没有再上一级了,直接报错
赋值规则
- 当你想给一个变量赋值的时候,那么就先要找到这个变量,在给他赋值
- 变量赋值规则:
先在自己作用域内部查找,有就直接赋值
没有就去上一级作用域内部查找,有就直接赋值
还没有再去上一级作用域查找,有就直接赋值
如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,再给他赋值
七十四、对象
- 对象是一个复杂数据类型
- 其实说是复杂,但是没有很复杂,只不过是存储了一些基本数据类型的一个集合
var obj={
num: 100
str: 'hel1o world'
boo: true
}
- 这里的{}和函数中的{}不一样
- 函数里面的是写代码的,而对象里面是写一些数据的
- 对象就是一个键值对的集合
- {}里面的每一个键都是一个成员
- 也就是说,我们可以把一些数据放在一个对象里面, 那么他们就互不干扰了
- 其实就是我们准备一个房子,把我们想要的数据放进去,然后把房子的地址给到变量名,当我们需要某一个数据的时候,就可以根据变量名里面存储的地址找到对应的房子,然后去房子里面找到对应的数据
1.创建对象
- 字面量的方式创建一个对象
//创建一个空对象
var obj = {}
//像对象中添加成员
obj.name = 'Jack'
obj.age = 18
- 内置构造函数的方式创建对象
//创建一个空对象
var obj = new object()
//向对象中添加成员
obj.name='Rose'
obj.age = 20
- object是js内置给我们的构造函数,用于创建一个对象使用的
2.数据类型之间存储的区别
- 既然我们区分了基本数据类型和复杂数据类型
- 那么他们之间就一定会存在一些区别
- 他们最大的区别就是在存储上的区别
- 我们的存储空间分成两种栈和堆
- 栈:主要存储基本数据类型的内容
- 堆:主要存储复杂数据类型的内容
基本数据类型在内存中的存储情况
- var num = 100, 在内存中的存储情况
- 直接在栈空间内有存储一个数据
复杂数据类型在内存中的存储情况
- 下面这个对象的存储
var obj={
name: 'Jack',
age: 18,
gender: '男'
}
- 复杂数据类型的存储
1.在堆里面开辟一个存储空间
2.把数据存储到存储空间内
3.把存储空间的地址赋值给栈里面的变量 - 这就是数据类型之间存储的区别
七十五、数组
- 什么是数组?
- 字面理解就是数字的组合
- 其实不太准确,准确的来说数组是一个数据的集合
- 也就是我们把一些数据放在一个盒子里面,按照顺序排好
[1, 2,3,'hel1o', true, false]
- 这个东西就是一个数组,存储着一些数据的集合
数据类型分类
- number / string / boolean / undefined / null / object / function / array / …
- 数组也是数据类型中的一种
- 我们简单的把所有数据类型分为两个大类基本数据类型和复杂数据类型
- 基本数据类型: number / string / boolean / undefined / null
- 复杂数据类型: object / function / array /…
1.创建一个数组
- 数组就是一个[]
- 在[]里面存储着各种各样的数据,按照顺序依次排好
字面量创建一个数组
- 直接使用[]的方式创建一个数组
//创建一个空数组
var arr1=[]
//创建一个有内容的数组
var arr2=[1,2,3]
内置构造函数创建数组
- 使用js的内置构造函数Array创建一个数组
//创建一个空数组
var arrl = new Array()
//创建一个长度为10的数组
var arr2 = new Array(10)
//创建一个有内容的数组
var arr3 = new Array(1, 2, 3)
2.数组的length
- length:长度的意思
- length就是表示数组的长度,数组里面有多少个成员,length就是多少
3.冒泡排序
- 先遍历数组,让挨着的两个进行比较,如果前一个比后一个大, 那么就把两个换个位置
- 数组遍历一遍以后,那么最后一个数字就是最大的那个了
- 然后进行第二遍的遍历,还是按照之前的规则,第二大的数字就会跑到倒数第二的位置
- 以此类推,最后就会按照顺序把数组排好了
4.选择排序
- 先假定数组中的第0个就是最小的数字的索引
- 然后遍历数组,只要有一个数字比我小,那么就替换之前记录的索引
- 直道数组遍历结束后,就能找到最小的那个索引,然后让最小的索弓|换到第0个的位置
- 再来第二趟遍历,假定第1个是最小的数字的索引
- 再遍历一次数组,找到比我小的那个数字的索引
- 遍历结束后换个位置
- 依此类推,也可以把数组排序好
5.数组的常用方法
- 数组是一个复杂数据类型,我们在操作它的时候就不能再想基本数据类型一样操作了
- 比如我们想改变一个数组
//创建一个数组
var arr=[1,2,3]
//我们想把数组变成只有1和2
arr= [1, 2]
- 这样肯定是不合理,因为这样不是在改变之前的数组
- 相当于新弄了一个数组给到arr这个变量了
- 相当于把arr里面存储的地址给换了,也就是把存储空间换掉了,而不是在之前的空间里面修改。所以我们就需要借助一些方法,在不改变存储空间的情况下,把存储空间里面的数据改变了
影响原数组的方法
push
- 后面追加元素
- 返回值 长度
pop
- 后面删除元素
- 返回值 删除的元素
unshift
- 前面追加元素
- 返回值 长度
shift
- 前面删除元素
- 返回值 删除的这个元素
splice
- 删除
- 增加
reverse
- 倒序
sort
- 排序
不影响原数组的方法
concat
- 拼接
join
- 数组==>字符串
slice
- 截取
indexOf
- -1 找不到
lastIndexOf
- -1 找不到
foreach
- 遍历
map
- 映射
filter
- 过滤
every
- 每一个
some
- 只要一个满足条件 就是true
find
reduce
- 叠加