JS 前面必须要加分号的情况: 1.立即执行函数 2.以数组开头的行,前面要加分号
tab栏切换使用 css 解决:
一.作用域、解构、箭头函数
1.作用域链.本质上是底层的变量查找机制
在函数被执行时,会优先查找当前函数作用域中查找变量,如果当前作用域查找不到,则会依次逐级查找父级作用域直到全局作用域。
总结: 1.嵌套关系的作用域串联起来形成了作用域链
2.相同作用域链中按着从小到大的规则查找变量
3.子作用域能够访问父作用域,父级作用域无法访问子级作用域
2.垃圾回收机制GC
JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收: JS环境中分配的内存,一般有如下生命周期:
1.内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存 2.内存使用:即读写内存,也就是使用变量、函数等 3.内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存
说明: 全局变量一般不会回收(除非关闭页面时会回收) 局部变量的值,不用时,一般会被自动回收掉 内存泄漏:程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏
垃圾回收机制GC--算法说明: 1.堆栈空间分配区别: 栈(操作系统):由操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面 堆(操作系统):一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放到堆里面 2.标记清除法核心: 标记清除算法将“不再使用的对象”定义为“无法达到的对象”,就是从根部(在JS中就是全局对象)出发时扫描内存中的对象,凡是能从根部到达的对象,都是还需要使用的,而那些无法触及到的对象被标记为不再使用,稍后进行回收
3.闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
闭包 = 内层函数 + 外层函数的变量 目的是:让外部也可以访问使用 函数内部的变量
作用:封闭数据,实现数据私有,外部也可以访问函数内部的变量; 闭包很有用,因为它允许将函数与其所操作的某些数据 (环境)关联起来
可能引起的问题:内存泄漏
// 实现数据私有 保护数据
function count() {
let i = 0 // —
function fn() { // |
i++ // > 闭包
console.log(`函数被调用了${i}次`) // |
} // —
return fn
}
const fun = count() // count() = fn = function fn() {}
fun() // 调用函数
// i 在使用完后应该被回收,但从根部出发能够找到i:window -> fun -> fn ->
// i导致i不会被回收,可能会造成内存泄漏
4. var 变量提升
var没有块作用域
var 变量提升:把所有var声明的变量提升到,当前作用域的最前面,只提升声明,不提升赋值
JS 内部会自动把所有函数声明,提升到当前作用域的最前面 只提升声明,不提升函数调用
声明函数表达式,必须先声明赋值,再调用
// JS内部会自动把所有函数声明,提升到当前作用域的最前面 // 只提升声明,不提升函数调用
fn()
function fn(){ console.log('函数提升') }
//相当于:
function fn(){ console.log('函数提升') }
fn()
// 声明函数表达式,必须先声明赋值,再调用
fun()
var fun = function(){ // 函数表达式是赋值,不是声明
console.log('函数表达式') // 在变量提升时,不提升赋值
}
// 相当于:
var fun // 只把函数声明提升了
fun()
fun = function(){
console.log('函数表达式')
}
5.函数参数
动态参数:arguments伪数组 ,只存在于函数里面
剩余参数: . . . 是语法,置于最末函数形参之前,用于获取多余的实参,是个真数组 ( √ 提倡使用)
function getSum(a,b...arr){
console.log(arr) // a=1 b=2 arr=[3,4,5]
}
getSum(1,2,3,4,5)
拓展:展开运算符. . . 将一个数组进行展开
运用场景:求数组最大值(最小值)、合并数组等 Math . max (1,2,3) 里面只能接字符型的数据
对象、数组等都能使用,不会修改原数组
// 将一个数组进行展开
const arr1 = [1,2,3,4,5]
const arr2 = [6,7,8]
console.log(...arr) // 1,2,3,4,5
console.log(Math.max(...arr)) // 5
const arr = [...arr1 , ...arr2] // arr = [1,2,3,4,5,6,7,8]
6.箭头函数 (箭头函数更适用于那些本来需要匿名函数的地方)
-
更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁,没有this,没有arguments,有剩余参数...arr 箭头函数属于表达式函数,因此不存在函数提升
-
在箭头函数出现之前,每一个新函数根据它是被如何调用的来定义这个函数的this值, 非常令人讨厌。 箭头函数不会创建自己的this,它只会从自己的作用域链 { } 的上一层沿用this。
// 1. 箭头函数 基本语法
const fn = () => {
console.log(123)
}
fn()
//2. 只有一个形参的时候,可以省略小括号
const fn = x => {
console.log(x)
}
fn(1)
// 3. 只有一行代码的时候,我们可以省略大括号
const fn = x => console.log(x)
fn(1)
// 4. 只有一行代码的时候,可以省略return
const fn = x => x + x
console.log(fn(1))
//5. 箭头函数可以直接返回一个对象 必须要加 ( ) 加括号的函数体返回对象字面量表达式
const fn = (uname) => ({ uname: uname })
console.log(fn('刘德华'))
// 1. 普通对象方法里面的this 谁调用指向谁
const obj = {
name: 'andy',
sayHi: function () {
console.log(this) // obj
}
}
obj.sayHi()
// 2. 箭头函数的this 是上一层作用域的this 指向
const fn = () => {
console.log(this) // window
}
fn()
// 3. 对象方法箭头函数 this
const obj = {
uname: 'pink老师',
sayHi: () => {
console.log(this) // this 指向谁? window
}
}
obj.sayHi()
// 4.特殊
const obj = {
uname: 'pink老师',
sayHi: function () {
console.log(this) // obj
let i = 10
const count = () => {
console.log(this) // obj
}
count()
}
}
obj.sayHi()
7.数组解构、对象解构
1.数组解构:把数组元素 快速批量的赋值给变量
// 数组解构 赋值
const arr = [100, 60, 80]
const [max, min, avg] = arr
console.log(max) // 100
// 交换2个变量的值
let a = 1
let b = 2; // 要加个 ;
[b, a] = [a, b]
console.log(a, b)
// 1. 变量多, 单元值少 , undefined
const [a, b, c, d] = [1, 2, 3] // d: undefined
// 2. 变量少, 单元值多
const [a, b] = [1, 2, 3]
// 3. 剩余参数 变量少, 单元值多
const [a, b, ...c] = [1, 2, 3, 4] // c: [3, 4] 真数组
// 4. 防止 undefined 传递 设置默认值
const [a = 0, b = 0] = [1, 2]
// 5. 按需导入赋值
const [a, b, , d] = [1, 2, 3, 4] // d: 4
// 多维数组解构
const arr = [1, 2, [3, 4]] // 只取3:arr[2][0])
const [a, b, [c, d]] = [1, 2, [3, 4]] // c: 3
2.对象解构是将对象属性和方法快速批量赋值给一系列变量 要求属性名和变量名必须一致
注意解构的变量名不要和外面的变量名冲突,否则报错
// 对象解构的语法
const { uname, age } = {age: 18, uname: 'pink老师' }
// 1. 对象解构的变量名 可以重新改名 旧变量名: 新变量名
const { uname: username, age } = { uname: 'pink老师', age: 18 }
// 2. 解构数组对象
const pig = [
{
uname: '佩奇',
age: 6
}
]
const [{ uname, age }] = pig // 变量名要相同 【{ }】 也要相同
// 多级对象解构:
const pig = {
name: '佩奇',
family: {
mother: '猪妈妈',
father: '猪爸爸',
sister: '乔治'
},
age: 6
}
const { name, family: { mother, father, sister } } = pig 要注明变量名,用 : 隔开
①多级对象解构案例
// 这是后台传递过来的数据
const msg = {
"code": 200,
"msg": "获取新闻列表成功",
"data": [
{
"id": 1,
"title": "5G商用自己,三大运用商收入下降",
"count": 58
},
{
"id": 2,
"title": "国际媒体头条速览",
"count": 56
},
{
"id": 3,
"title": "乌克兰和俄罗斯持续冲突",
"count": 1669
},
]
}
// 需求1: 请将以上msg对象 采用对象解构的方式 只选出 data 方面后面使用渲染页面
const { data }=msg
console.log(data);
// 需求2: 上面msg是后台传递过来的数据,我们需要把data选出当做参数传递给 函数
function render( { data }) {
console.log(data);
}