作用域链
JS垃圾回收机制(Garbage Collection):GC
概述
内存的生命周期
算法说明 —— 引用计数
IE采用的引用技术算法,定义内存不再使用,就是看一个对象是否由指向它的引用,没有引用就回收对象
function fn() {
let o1 = {}
let o2 = {}
o1.a = o2
o2.a = o1
return '引用计数无法回收'
}
fn()
算法说明 —— 标记清楚法
现代的IE浏览器已经不在使用引用计数算法了,现在浏览器通用的大多都是基于标记清楚算法的某些改进算法
闭包
// 闭包简单写法
/*
function outer(){
let a = 10
function fn(){
console.log(a)
}
fn()
}
outer()
*/
// 常见的闭包形式(外部可以访问使用函数内部的变量)
function outer(){
let a = 100
function fn(){
console.log(a)
}
return fn
}
const fun = outer()
fun()
这样实现了数据私有,无法直接修改 a 的值
变量提升
变量提升是 JavaScript 中比较异常的现象,它允许在声明变量之前即被访问(仅存于 var 声明变量)
函数提升
函数提升与变量提升比较类似,是指函数在声明之前即刻被调用
// 调用函数
foo()
// 声明函数
function foo(){
console.log("声明之前即被调用...")
}
// 不存在提升现象
bar() // 错误
var bar = function(){
console.log("函数表达式不存在提升现象")
}
函数参数
arguments是函数内部内置的伪数组变量,包含了调用函数时传入的所有实参
function getSum(){
// arguments 动态参数【只存在于函数里面】
// 伪数组,存储的是传递过来的实参
let sum = 0
for (let i = 0;i < arguments.length;i++){
sum += arguments[i]
}
console.log(sum)
}
getSum(2,3,4)
getSum(2,3,4,4,4,41,2,2)
剩余参数允许我们将一个不定数量的参数表示为一个数组
function getSum(a,b,...arr){
console.log(arr)
}
getSum(2,3) // []
getSum(2,3,4,5) // [ 4, 5 ]
展开运算符
运用场景:求数组最大值最小值、合并数组等
const arr1 = [1,2,3]
// 展开运算符:展开数组
console.log(...arr1) // 1 2 3
// 使用场景:例如Math.max()——参数不能为数组,所以可以将数组来展开为 1,2,3的形式
console.log(Math.max(...arr1)) // 3
console.log(Math.min(...arr1)) // 1
// 用来合并数组
const arr2 = [1,2,3]
const arr3 = [4,5,6]
const arr = [...arr2,...arr3]
console.log(arr) // [ 1, 2, 3, 4, 5, 6 ]
基本语法
// 函数表达式
/* const fn = function(){
console.log(1)
} */
// 箭头函数:简化函数表达式
const fn1 = (x) => {
console.log(x)
}
fn1(1)
// 1.当只有一个行参的时候,可以省略小括号
const fn2 = x => {
console.log(x)
}
fn2(1)
// 2.当函数体只有一行代码时,可以省略大括号
const fn3 = x => console.log(x)
fn3(1)
// 3.当函数体只有一行代码,且需要返回的时候,可以省略return
const fn4 = x => x + x
console.log(fn4(1))
// 4.箭头函数可以直接返回一个对象【返回值为()起来的为对象字面量】
const fn5 = uname => ({uname:uname})
console.log(fn5("马浩楠")) // Object { uname: "马浩楠" }
箭头函数参数
// 利用箭头函数的剩余参数求和
const fun = (...arr) => {
let sum = 0
for (let i = 0;i < arr.length ;i++){
sum += arr[i]
}
return sum
}
console.log(fun(2,3,4))
箭头函数 this
箭头函数不会创建自己的this,只会从自己的作用域链的上一层沿用this
// 以前的this指向:谁调用,this指向谁
console.log(this) // window
// 普通函数
function fun(){
console.log(this) // window
}
// 对象方法中的this
const obj = {
name: "马浩楠",
sayHi:function(){
console.log(this) // obj
}
}
obj.sayHi()
// 箭头函数的this,指的是上一层作用域的this指向
const fn = () => {
console.log(this) // window
}
// 对象中的this
const o = {
name: "马浩楠",
sayHi:() => {
console.log(this) // window
}
}
// 函数嵌套函数中的this
const ob = {
name:"马浩楠",
sayHi: function() {
console.log(this) // ob
const count = () => {
console.log(this) // ob
}
count()
}
}
开发中,事件回调函数使用箭头函数时,this 为全局的window,因此:DOM事件回调函数为了简便,不推荐使用箭头函数
基本语法
// 数组解构
const [max,min,avg] = [100,60,80]
console.log(max)
console.log(min)
console.log(avg)
典型应用:交互两个变量值
// 交换两个变量的值【注意;】
let a = 1
let b = 2;
[b, a] = [a, b]
console.log(a) // 2
console.log(b) // 1
js前必须加分号情况
(function(){})();
// 或者
;(function(){})()
解构中特殊情况
const [a, b, c, d] = ["小米", "苹果", "华为"]
console.log(a) // 小米
console.log(b) // 苹果
console.log(c) // 华为
console.log(d) // undefined
变量的数量大于单元之数量的时候,多余的变量将被赋值为 undefined
const [a, b] = ["小米", "苹果", "华为"]
console.log(a) // 小米
console.log(b) // 苹果
const [a, b, ...tel] = ["小米", "苹果", "华为", "格力"]
console.log(a) // 小米
console.log(b) // 苹果
console.log(tel) // ["华为", "格力"]
const [a = "手机", b = "华为"] = ["小米"]
console.log(a) // 小米
console.log(b) // 华为
const [a, [b, c] = ["小米", ["苹果", "华为"]]
console.log(a) // 小米
console.log(b) // 苹果
console.log(tel) // 华为
基本语法
// 解构语法 【变量名和对象属性名必须一致】
const {uname, age} = {uname: "马浩楠", age: 22}
// 等价于: const uname = obj.uname
console.log(uname)
console.log(age)
// 对象解构的变量名:更改变量名
const {uname:userName, age1} = {uname: "马浩楠", age1: 22}
console.log(userName)
console.log(age1)
// 解析数组对象
const [{name, longevity}] = [{name: "浩楠", longevity: 100}]
console.log(name)
console.log(longevity)
注意点
对象多级解构
const pig = {
name: "佩奇",
family: {
mother: "猪妈妈",
father: "猪爸爸",
sister: "乔治"
}
}
// 多级对象解构
/* 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: "乔治"
}
}
]
const [{name, family:{mother, father, sister}}] = person
console.log(name)
console.log(mother)
console.log(father)
console.log(sister)
遍历数组 forEach 方法
const arr = ["red", "blue", "green"]
arr.forEach(function(item, index){
console.log(item) // 元素值
console.log(index) // 索引号
})
// 使用箭头函数
arr.forEach((item,index) => {
console.log(item)
console.log(index)
})
案例
<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, index) => {
str += `
<div class="item">
<img src="${item.picture}" alt="${item.id}">
<p class="name">${item.name}</p>
<p class="price">${item.price}</p>
</div>
`
})
document.querySelector(".list").innerHTML = str
</script>
</body>
筛选数组 filter 方法
filter方法创建一个新的数组,新数组中的元素是通过筛选符合条件后的所有元素
const data = [10,20,30]
const newData = data.filter(item => {
return item >= 20
})
console.log(newData) // 20,30
<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',
},
]
function render(data){
let str = ""
data.forEach(item => {
const {name, price, picture} = item
str += `
<div class="item">
<img src="${picture}" alt="">
<p class="name">${name}</p>
<p class="price">${price}</p>
</div>
`
})
document.querySelector(".list").innerHTML = str
}
// 打开页面进行渲染
render(goodsList)
const filter = document.querySelector(".filter")
filter.addEventListener("click", function(e){
if(e.target.tagName === "A"){
switch(e.target.dataset.index){
case "1":
render(goodsList.filter(item => item.price > 0 && item.price <= 100))
break;
case "2":
render(goodsList.filter(item => item.price > 100 && item.price <= 300))
break;
case "3":
render(goodsList.filter(item => item.price >= 300))
break;
default:
render(goodsList)
break;
}
}
})
</script>
</body>