作用域
局部作用域
全局作用域
作用域链
JS垃圾回收机制
闭包
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 统计函数调用次数let i=0function fn(){i++console.log(i)}// i是全局变量,容易被修改,改为局部变量// 闭包形式function count(){let i=0function fn(){i++console.log(i)}return fn}const fun = count()</script>
</body>
</html>
变量提升
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 1. 把所有var声明的变量提升到 当前作用域的最前面// 2. 只提升声明, 不提升赋值// var num// console.log(num + '件')// num = 10// console.log(num)function fn() {console.log(num)var num = 10}fn()</script>
</body></html>
函数进阶
函数提升
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>var fun// 1. 会把所有函数声明提升到当前作用域的最前面// 2. 只提升函数声明,不提升函数调用// fn()// function fn() {// console.log('函数提升')// }// fun()// var fun = function () {// console.log('函数表达式')// }// 函数表达式 必须先声明和赋值, 后调用 否则 报错</script>
</body></html>
函数参数
动态参数
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>function getSum() {// arguments 动态参数 只存在于 函数里面// 是伪数组 里面存储的是传递过来的实参// console.log(arguments) [2,3,4]let sum = 0for (let i = 0; i < arguments.length; i++) {sum += arguments[i]}console.log(sum)}getSum(2, 3, 4)getSum(1, 2, 3, 4, 2, 2, 3, 4)</script>
</body></html>
剩余参数
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>function getSum(a, b, ...arr) {console.log(arr) // 使用的时候不需要写 ...}getSum(2, 3)getSum(1, 2, 3, 4, 5)</script>
</body></html>
展开运算符
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const arr1 = [1, 2, 3]// 展开运算符 可以展开数组// console.log(...arr)// console.log(Math.max(1, 2, 3))// ...arr1 === 1,2,3// 1 求数组最大值console.log(Math.max(...arr1)) // 3console.log(Math.min(...arr1)) // 1// 2. 合并数组const arr2 = [3, 4, 5]const arr = [...arr1, ...arr2]console.log(arr)</script>
</body></html>
箭头函数(重要)
基本写法
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const fn = function () {// console.log(123)// }// 1. 箭头函数 基本语法// const fn = () => {// console.log(123)// }// fn()// const fn = (x) => {// console.log(x)// }// fn(1)// 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('刘德华'))</script>
</body></html>
箭头函数参数
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 1. 利用箭头函数来求和const getSum = (...arr) => {let sum = 0for (let i = 0; i < arr.length; i++) {sum += arr[i]}return sum}const result = getSum(2, 3, 4)console.log(result) // 9</script>
</body></html>
箭头函数 this
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 以前this的指向: 谁调用的这个函数,this 就指向谁// console.log(this) // window// // 普通函数// function fn() {// console.log(this) // window// }// window.fn()// // 对象方法里面的this// const obj = {// name: 'andy',// sayHi: function () {// console.log(this) // obj// }// }// obj.sayHi()// 2. 箭头函数的this 是上一层作用域的this 指向// const fn = () => {// console.log(this) // window// }// fn()// 对象方法箭头函数 this// const obj = {// uname: 'pink老师',// sayHi: () => {// console.log(this) // this 指向谁? window// }// }// obj.sayHi()const obj = {uname: 'pink老师',sayHi: function () {console.log(this) // objlet i = 10const count = () => {console.log(this) // obj }count()}}obj.sayHi()</script>
</body></html>
解构赋值
数组解构
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const arr = [100, 60, 80]// 数组解构 赋值// // const [max, min, avg] = arrconst [max, min, avg] = [100, 60, 80]// // const max = arr[0]// // const min = arr[1]// // const avg = arr[2]console.log(max) // 100console.log(avg) // 80// 交换2个变量的值let a = 1let b = 2;[b, a] = [a, b]console.log(a, b)</script>
</body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 1. 立即执行函数要加// (function () { })();// (function () { })();// 2. 使用数组的时候// const arr = [1, 2, 3]const str = 'pink';[1, 2, 3].map(function (item) {console.log(item)})let a = 1let b = 2;[b, a] = [a, b]console.log(a, b)</script>
</body></html>
练习
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>const [hr,lx,mi,fz] = ['海尔', '联想', '小米', '方正'] function getValue(){return [100,60]}const [max,min] = getValue()console.log((max))console.log((min))</script>
</body>
</html>
数组解构
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const pc = ['海尔', '联想', '小米', '方正'];// [hr, lx, mi, fz] = pc// console.log(hr, lx, mi, fz);// function getValue() {// return [100, 60]// }// [max, min] = getValue()// console.log(max, min);// const pc = ['海尔', '联想', '小米', '方正']// const [hr, lx, mi, fz] = ['海尔', '联想', '小米', '方正']// console.log(hr)// console.log(lx)// console.log(mi)// console.log(fz)// // 请将最大值和最小值函数返回值解构 max 和min 两个变量// function getValue() {// return [100, 60]// }// const [max, min] = getValue()// console.log(max)// console.log(min)// 1. 变量多, 单元值少 , undefined// const [a, b, c, d] = [1, 2, 3]// console.log(a) // 1// console.log(b) // 2// console.log(c) // 3// console.log(d) // undefined// 2. 变量少, 单元值多// const [a, b] = [1, 2, 3]// console.log(a) // 1// console.log(b) // 2// 3. 剩余参数 变量少, 单元值多// const [a, b, ...c] = [1, 2, 3, 4]// console.log(a) // 1// console.log(b) // 2// console.log(c) // [3, 4] 真数组// 4. 防止 undefined 传递// const [a = 0, b = 0] = [1, 2]// const [a = 0, b = 0] = []// console.log(a) // 1// console.log(b) // 2// 5. 按需导入赋值// const [a, b, , d] = [1, 2, 3, 4]// console.log(a) // 1// console.log(b) // 2// console.log(d) // 4// const arr = [1, 2, [3, 4]]// console.log(arr[0]) // 1// console.log(arr[1]) // 2// console.log(arr[2]) // [3,4]// console.log(arr[2][0]) // 3// 多维数组解构// const arr = [1, 2, [3, 4]]// const [a, b, c] = [1, 2, [3, 4]]// console.log(a) // 1// console.log(b) // 2// console.log(c) // [3,4]const [a, b, [c, d]] = [1, 2, [3, 4]]console.log(a) // 1console.log(b) // 2console.log(c) // 3console.log(d) // 4</script></body></html>
对象解构
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 对象解构// const obj = {// uname: 'pink老师',// age: 18// }// obj.uname// obj.age // const uname = 'red老师'// 解构的语法// const { uname, age } = {age: 18, uname: 'pink老师' }// // 等价于 const uname = obj.uname// // 要求属性名和变量名必须一直才可以// console.log(uname)// console.log(age)// 1. 对象解构的变量名 可以重新改名 旧变量名: 新变量名// const { uname: username, age } = { uname: 'pink老师', age: 18 }// console.log(username)// console.log(age)// 2. 解构数组对象const pig = [{uname: '佩奇',age: 6}]const [{ uname, age }] = pigconsole.log(uname)console.log(age)</script>
</body></html>
多级对象解构
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const pig = {// name: '佩奇',// family: {// mother: '猪妈妈',// father: '猪爸爸',// sister: '乔治'// },// age: 6// }// // 多级对象解构// const { name, family: { mother, father, sister } } = pig// console.log(name)// console.log(mother)// console.log(father)// console.log(sister)const person = [{name: '佩奇',family: {mother: '猪妈妈',father: '猪爸爸',sister: '乔治'},age: 6}]const [{ name, family: { mother, father, sister } }] = personconsole.log(name)console.log(mother)console.log(father)console.log(sister)</script>
</body></html>
for each
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>const arr = ['red','green','pink']const result = arr.forEach(function(item,index){console.log(item)console.log(index)})// 无返回值,适合遍历数组对象</script>
</body>
</html>
案例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>商品渲染</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.list {width: 990px;margin: 0 auto;display: flex;flex-wrap: wrap;padding-top: 100px;}.item {width: 240px;margin-left: 10px;padding: 20px 30px;transition: all .5s;margin-bottom: 20px;}.item:nth-child(4n) {margin-left: 0;}.item:hover {box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);transform: translate3d(0, -4px, 0);cursor: pointer;}.item img {width: 100%;}.item .name {font-size: 18px;margin-bottom: 10px;color: #666;}.item .price {font-size: 22px;color: firebrick;}.item .price::before {content: "¥";font-size: 14px;}</style>
</head><body><div class="list"><!-- <div class="item"><img src="" alt=""><p class="name"></p><p class="price"></p></div> --></div><script>const goodsList = [{id: '4001172',name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',price: '289.00',picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',},{id: '4001594',name: '日式黑陶功夫茶组双侧把茶具礼盒装',price: '288.00',picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',},{id: '4001009',name: '竹制干泡茶盘正方形沥水茶台品茶盘',price: '109.00',picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',},{id: '4001874',name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',price: '488.00',picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',},{id: '4001649',name: '大师监制龙泉青瓷茶叶罐',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',},{id: '3997185',name: '与众不同的口感汝瓷白酒杯套组1壶4杯',price: '108.00',picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',},{id: '3997403',name: '手工吹制更厚实白酒杯壶套装6壶6杯',price: '99.00',picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',},{id: '3998274',name: '德国百年工艺高端水晶玻璃红酒杯2支装',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',},]let str = ''goodsList.forEach(item => {const {name,price,picture} = itemstr += `<div class="item"><img src="${picture}" alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`})document.querySelector('.list').innerHTML = str</script>
</body></html>
筛选
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const arr = [10, 20, 30]// const newArr = arr.filter(function (item, index) {// // console.log(item)// // console.log(index)// return item >= 20// })// 返回的符合条件的新数组const newArr = arr.filter(item => item >= 20)console.log(newArr)</script>
</body></html>
综合案例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>商品渲染</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.list {width: 990px;margin: 0 auto;display: flex;flex-wrap: wrap;}.item {width: 240px;margin-left: 10px;padding: 20px 30px;transition: all .5s;margin-bottom: 20px;}.item:nth-child(4n) {margin-left: 0;}.item:hover {box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);transform: translate3d(0, -4px, 0);cursor: pointer;}.item img {width: 100%;}.item .name {font-size: 18px;margin-bottom: 10px;color: #666;}.item .price {font-size: 22px;color: firebrick;}.item .price::before {content: "¥";font-size: 14px;}.filter {display: flex;width: 990px;margin: 0 auto;padding: 50px 30px;}.filter a {padding: 10px 20px;background: #f5f5f5;color: #666;text-decoration: none;margin-right: 20px;}.filter a:active,.filter a:focus {background: #05943c;color: #fff;}</style>
</head><body><div class="filter"><a data-index="1" href="javascript:;">0-100元</a><a data-index="2" href="javascript:;">100-300元</a><a data-index="3" href="javascript:;">300元以上</a><a href="javascript:;">全部区间</a></div><div class="list"><!-- <div class="item"><img src="" alt=""><p class="name"></p><p class="price"></p></div> --></div><script>// 2. 初始化数据const goodsList = [{id: '4001172',name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',price: '289.00',picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',},{id: '4001594',name: '日式黑陶功夫茶组双侧把茶具礼盒装',price: '288.00',picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',},{id: '4001009',name: '竹制干泡茶盘正方形沥水茶台品茶盘',price: '109.00',picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',},{id: '4001874',name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',price: '488.00',picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',},{id: '4001649',name: '大师监制龙泉青瓷茶叶罐',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',},{id: '3997185',name: '与众不同的口感汝瓷白酒杯套组1壶4杯',price: '108.00',picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',},{id: '3997403',name: '手工吹制更厚实白酒杯壶套装6壶6杯',price: '99.00',picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',},{id: '3998274',name: '德国百年工艺高端水晶玻璃红酒杯2支装',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',},]// 1. 渲染函数 封装function render(arr) {// 声明空字符串let str = ''// 遍历数组arr.forEach(item => {// 解构const { name, picture, price } = itemstr += `<div class="item"><img src=${picture} alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`})// 追加给listdocument.querySelector('.list').innerHTML = str}render(goodsList)// 2. 过滤筛选 document.querySelector('.filter').addEventListener('click', e => {// e.target.dataset.index e.target.tagNameconst { tagName, dataset } = e.target// 判断 if (tagName === 'A') {// console.log(11) // arr 返回的新数组let arr = goodsListif (dataset.index === '1') {arr = goodsList.filter(item => item.price > 0 && item.price <= 100)} else if (dataset.index === '2') {arr = goodsList.filter(item => item.price >= 100 && item.price <= 300)} else if (dataset.index === '3') {arr = goodsList.filter(item => item.price >= 300)}// 渲染函数render(arr)}})</script>
</body></html>