闭包
=> 函数的高级应用
=> 回顾函数
function fun(){
console.log("内容")
}
let fun = function(){
console.log("内容")
}
fun()
let fun = new Function('console.log("内容")')
补充函数内存结构
函数销毁的执行空间
函数不被销毁的执行空间
了解闭包
闭包是javascript语法现象,是函数的高级用法
闭包形成条件:
1. 函数嵌套- 外层函数 内层函数
2. 外部引用返回的内层函数
3. 内层使用外层函数变量
闭包作用:
1. 形成不被销毁的执行空间,延长变量生命周期, 缺点,容易引起内存泄露
2. 外部可以访问内部函数的变量- 变量作用域扩展 - 没有形成闭包,只能内部函数访问外层函数变量
3. 形成块作用域定义私有变量
闭包三种写法
闭包的特点
闭包的应用
柯里化函数
将有多个形参的函数转换成多个只有一个形参的函数
f(a,b,c) -> fn(a)
fn1(b)
fn2(c)
f(a,b,c) -> fn(a)(b)(c)
通用柯里化函数
通用柯里化函数
1. 定义可以变长度形参函数
function fn(...args){
console.log(args) // [1,2,3]
}
fn(1,2,3)
2. 定义一个函数,参数也是函数,参数函数它参数个数
function fn(func){
console.log(fn.length)
}
3.
柯里化日志工具函数
/**
* log 日志工具函数
* date: 日期时间 14:45 -> new Date()
* importance: 日志级别 DEBUG(调试日志) INFO(普通日志) WARN(警告日志) ERROR(错误日志)
* message: 日志信息
* [14:45]-[INFO] 日志工具函数封装
*/
function log(date, importance, message) {
console.log(
`[${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}]-[${importance}] :${message}`
)
}
// log(new Date(),'DEBUG','日志工具函数封装')
// log(new Date(),'ERROR','这是错误信息 typeErrry 类型错误')
let curryLog = currying(log)
// curryLog(new Date())('INFO')('柯里化函数')
// 柯里化日期
let curryDateLog = curryLog(new Date())
curryDateLog('INFO','柯里化日期')
// 柯里化日志级别
let curryDebugLog = curryDateLog('DEBUG')
curryDebugLog('柯里化日志级别1')
curryDebugLog('柯里化日志级别2')
function currying(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this,args) //sum(10,20,30)
} else {
return function (...arg2) {
let arg = [...args, ...arg2]
return curried.apply(this, arg)
}
}
}
}
继承
了解继承
面向对象
- 面向对象编程思想
找对象,解决问题,如果对象不存在,封装对象
- 构造函数
// ES5 人类
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.say = function(){
console.log('说话')
}
let p1 = new Person('jack',18)
let p2 = new Person('rose',20)
- ES6 class类
// 人类
class Person{
construtor(name,age){
this.name = name
this.age = age
}
say(){
console.log('说话')
}
}
let p1 = new Person('jack',18)
let p2 = new Person('rose',20)
面向对象三大特性之一 继承
1. 封装 对象属性和方法
2. 继承
3. 多态 一个事物有多种表现形态
let num = 100 // number
num = '100' // string
继承
=>子类继承父类,子类就拥有父的属性和方法
=>表示类与类之间的关系, 父类和子类关系
现实生活中的继承
儿子继承父亲money、home、car
ES5 实现继承
1. 构造函数继承
在子类构造函数中调用父类构造函数
2. 拷贝继承-实现原型属性和方法继承
3. 原型继承 - 改变原型指向实现 - 将父类实例复制子类原型对象
4. 组合继承
构造函数 + 拷贝继承
代码:
// 父类
function Parent() {
this.money = 100000
this.home = '房子'
this.playGame = function () {
console.log('玩游戏')
}
}
Parent.prototype.swiming = function(){
console.log('游泳');
}
// 子类
function Son() {
// 构造函数继承
Parent.call(this)
this.name = 'jack'
}
// 拷贝继承-实现原型属性和方法继承
for(const key in Parent.prototype){
Son.prototype[key] = Parent.prototype[key]
}
let parent1 = new Parent() // parent1是有money和房子的父类实例对象
let s1 = new Son() // 名为jack的儿子实例对象
// 测试儿子是否继承到父类属性和方法
s1.playGame()
console.log(s1.money, s1.home);
s1.swiming()
构造函数继承
原型拷贝继承
示例
原型继承
// 父类
function Parent() {
this.money = 100000
this.home = '房子'
this.playGame = function () {
console.log('玩游戏')
}
}
Parent.prototype.swiming = function(){
console.log('游泳');
}
// 子类
function Son() {
this.name = 'jack'
}
// 原型继承 - 改变原型指向实现 - 将父类实例复制子类原型对象
Son.prototype = new Parent()
let parent1 = new Parent() // parent1是有money和房子的父类实例对象
let s1 = new Son() // 名为jack的儿子实例对象
// 测试原型继承
s1.swiming()
s1.playGame()
console.log(s1.money, s1.home);
// console.dir(Parent.prototype.__proto__);
// console.dir(Object.prototype);
// console.dir(Son.prototype.__proto__);
组合继承
class类继承
// 父类
class Parent {
constructor() {
this.money = 100000
this.home = '房子'
}
playGame(){
console.log('玩游戏');
}
swiming(){
console.log('游泳');
}
}
// 子类Son继承父类Parent
class Son extends Parent{
constructor(name){
// 先实例化父类
super() //super关键字表示父类构造器
this.name = name
}
}
let parent1 = new Parent()
let son1 = new Son('jack')
son1.swiming()
son1.playGame()
console.log(son1.money, son1.home);