进阶ES6
作用域的概念加深对js理解
let、const申明的变量,在花括号中会生成块作用域,而var就不会生成块作用域
作用域链本质上就是底层的变量查找机制
作用域链查找的规则是:优先查找当前作用域先把的变量,再依次逐级找父级作用域直到全局作用域。
垃圾回收机制GC
全局变量一般不会回收除非关闭页面,一般情况下局部变量的值,不用了,会被自动回收掉
内存泄漏:程序中分配的内存由于某种原因程序未释放或者无法释放叫做内存泄漏
js垃圾回收—算法说明
缺点:嵌套引用,如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄漏
闭包
- 简单理解:闭包 = 内层函数 + 外层函数的变量
代码演示:
function outer(){const a = 1function f(){console.log(a)}f()
}
outer()
-
闭包的作用: 外部也可以访问函数内部的变量
-
闭包的应用,记录函数被调用的次数
let i = 0
function fn() {i++console.log(`函数被调用了${i}次`)
}
- 全局变量容易被修改,有风险,修改成闭包的形式
// 统计函数被调用的次数----闭包形式
function count(){let i = 0function fn() {i++console.log(`函数被调用了${i}次`)}return fn
}
const fun = count()
变量提升(只提升声明,不提升赋值)
// 1. 把所有var声明的变量提升到当前作用域的最前面
// 2. 只提升变量名, 不提升赋值
// var num
console.log(num + '件')
var num = 10
// 打印结果为 undefined件
函数进阶
函数提升(只提升声明,不提升赋值)
// 1. 会把所有函数声明提升到当前作用域的最前面
// 2. 只提升函数声明, 不提升函数调用
fn()
function fn(){console.log('函数提升')
}
函数参数
- 动态参数(箭头函数中没有)
// 计算所有参数的和
function sum(){let s = 0for (let i = 0; i < arguments.length; i++){s += arguments[1]}console.log(s)
}// 调用求和函数
sum(5, 10) // 两个参数
sum(1, 2, 4) // 三个参数
总结:
- arguments 是一个伪数组, 只存在于函数中
- arguments 的作用是动态的获取函数的实参
- 可以通过for 循环依次得到传过来的实参
- 剩余参数(在函数中使用的时候,不需要加…)
- …是语法符号,置于最末函数形参之前, 用于获取多余的实参
- 借助…获取的剩余实参,是个真数组
- 展开运算符(不会修改原数组)
- 典型的使用场景:求数组的最大值
const arr = [1, 2, 3]
console.log(Math.max(...arr)) // 3
- 用于合并数组
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = [...arr1, ...arr2]
console.log(arr3) // 1, 2, 3, 4, 5, 6
箭头函数
const fn = () =>{console.log(123)
}
fn()
// 只有一个形参的时候可以省略小括号
const fn = x => {console.log(x)
}
fn(1)
// 只有一行代码的时候, 我们可以省略大括号
const fn = x => console.log(x)
fn(1)
// 只有一行代码,可以省略return
const fn = (x, y) => x + y
console.log(fn(1, 2)) // 3
// 箭头函数可以直接返回一个对象
const fn = (uname) => ({uname: uname})
fn('刘德华')
- 箭头函数+剩余参数
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
解构赋值
- 数组解构
- 数组解构是将数组中的单元值,快速的赋值给一系列变量的简洁语法
const arr = [100, 60, 80]
// 数组结构 赋值
const [max, min, avg] = arr
// const max = arr[0]
// const min = arr[1]
// const avg = arr[2]
console.log(max) // 100
console.log(avg) // 80
- 可以用于交换变量
let a = 1
let b = 2; // 这个地方一定要加;不加就报错
[b, a] = [a, b]
console.log(a, b) // 2, 1// 1. 立即执行函数要加
(function () { })();
(function () { })();
// 2. 使用数组的时候
const str = 'pink';
[1, 2, 3].map(function (item) {console.log(item)
})
const [a, b, ...c] = [1, 2, 3, 4]
console.log(a) // 1
console.log(b) // 2
console.log(c) // [3, 4]// 防止undefined 传递
const [a = 0, b = 0] = []
cosnole.log(a) // 0
console.log(b) // 0// 按需求导入,忽略某些值
const [a, b, ,c] = [1, 2, 3, 4]
console.log(a) // 1
cosnole.log(b) // 2
console.log(c) // 4
- 多维数组的解构
对象解构
// 对象解构语法(要求声明的变量,必须和属性名相同,并且不能与外部变量名冲突)
const { uname, age } = { uname: 'hello', age: 18}
console.log(uname) // hello
console.log(age) // 18// 修改变量名
const { uname: name1, age } = { uname: 'hello', age: 18}
console.log(name1) // hello
console.log(age) // 18
- 多级对象解构
forEach方法
深入对象
创建对象的三种方式
- 构造函数来创建对象(用来创建多个类似的对象)
function Pig(name, age, gender) {this.name = namethis.age = agethis.gener = gender
}
// 创建佩奇对象
const Peppa = new Pig('佩奇', 6, '女')
// 创建乔治对象
const George = new Pig('乔治', 3, '男')
- 构造函数的约定
- 他们的命名以大写字母开头
- 他们只能用new来操作执行
- new 实例化执行过程
- 创建新对象
- 构造函数this指向新对象
- 执行构造函数代码,修改this, 添加新的属性
- 返回新对象
实例成员&静态成员
实例成员:通过够着函数创建对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)
静态成员:构造函数的属性和方法被称为静态成员(静态属性和静态方法)
基本包装类型
内置构造函数
const o = { uname : 'kwh', age : 18}
// 获取所有的属性名
console.log(Object.keys(o))
// 获取所有的属性值
console.log(Object.values(o))const oo = {}
Object.assign(oo, o) // 对象的拷贝
// 数组reduce方法
// arr.reduce(function(上一次值, 当前值){}, 初始值)
const arr = [1, 5, 8]// 1. 没有初始值
const total = arr.reduce(function (prev, current){return pre + current
})
console.log(total) // 14// 2. 有初始值(在有初始值的情况下,累加后需要将初始值也一并加上)
const total = arr.reduce(function (prev, current){return prev + current
}, 10)
console.log(total) // 24// 3. 箭头函数的写法
const total = arr.reduce((prev, current) => prev + current, 10)
console.log(total)
如果遇到对象累加,一定要给初始值,不然prev就是对象中的第一个元素
find方法最常用的场景
const arr = [{name: '小米',price: 1999},{name: '华为',price: 3999}
]
// 找出小米这个对象,并且返回这个对象
arr.find(function(item){return item.name === '小米'
})
小案例
const spec = { size: '40cm*40cm', color: '黑色'}
//1. 所有的属性值取过来
console.log(Object.values(spec))
//2. 转换为字符串 join('/')
console.log(Object.values(spec).join('/'))
//3. 展示在页面上
document.querySelector('div').innerHTML = Object.values(spec).join('/')
// 判断是不是以某个字符开头
const str = 'pink老师上课中'
console.log(str.startsWith('pink'))
<body><div></div><script>const gift = '50g的茶叶, 清洗球'// 1. 把字符串拆分为数组// console.log(gift.split(','))// 2. 根据数组元素的个数, 生成 对应 span标签const str = gift.split(',').map(function (item){return `<span>【赠品】${item}</span><br>`}).join('')// console.log(str)document.querySelector('div').innerHTML = str</script>
</body>
// 代码优化
document.querySelecter('div').innerHTML = gift.split(',').map(item => `<span>【赠品】 ${item}</span> <br>`).join('')
Number
toFixed()方法
// 当toFixed方法中不再传递参数的时候,就相当于四舍五入
const num = 10.923
console.log(num.toFixed()) // 11// 当toFixed方法传入参数的时候,小括号内即为限制小数点保留几位
console.log(num.toFixed(2)) // 10.92
深入面相对象
面向过程:分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现
面向对象:把事务分解为一个个对象,然后由对象之间分工与合作
- 面向对象的特征:
- 封装性
- 继承性
- 多态性
- 构造函数
公共的属性和方法封装到Star 构造函数里面了
function Star(uname, age){this.uname = unamethis.age = agethis.sing = function() {console.log('唱歌')}
}
const ldh = new Star('刘德华', 55)
const zxy = new Star('张学友', 58)
- js实现面向对象需要借助于谁来实现?
- 构造函数
- 构造函数存在什么问题?
- 在存储复杂数据类型的时候,会出现浪费内存
原型
- 构造函数通过原型分配的函数是所有对象所共享的。
- javaScript规定, 每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象
- 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
- 我们可以把那些不变的方法,直接定义在prootype对象上,这样所有对象的实例就可以共享这些方法
- 构造函数和原型对象中的this都指向实例化的对象
// 1. 公共的属性卸载构造函数中
function Star(uname, age){this.uname = unamethis.age = age
}
// 2. 公共的方法卸载原型对象身上
Star.prototype.sing = function(){console.log('唱歌')
}
const ldh = new Star('刘德华', 55)
const zxy = new Star('张学友', 58)
console.log(ldh.sing === zxy.sing) // true
- 构造函数和原型对象中的this都指向实例化的对象
自定义 数组扩展方法 求和 和 最大值
- 定义的这个歌方法, 要在任何一个数组实例对象都可以使用
- 自定义的方法写到 数组.prototype身上
- 求数组中的最大值
const arr = [1, 2, 3]
Array.prototype.max = function () {// 展开运算符return Math.max(...this)// 原型函数里面的this 指向实例对象 arr
}
console.log(arr.max()) // 3
console.log([1, 5, 9].max()) // 9// 求和
Array.prototype.sum = function() {return this.reduce( (prev, item) => prev + item, 0)
}
console.log([1, 2, 3].sum()) // 6
constructor属性
- constructor 这个单词的意思就是:构造函数
- 每个原型对象里都有个constructor属性
- 作用:指向该原型对象的构造函数
console.log(Star.prototype.constructor === Star) // trueStar.prototype = {// 重新指回创造这个原型对象的 构造函数constructor: Star,sing: function(){console.log('唱歌')},dance: function () {console.log('跳舞')}
}
console.log(Star.prototype)