JS闭包、柯里化函数、继承

71 阅读4分钟

闭包

=> 函数的高级应用

          => 回顾函数

              function fun(){
                  console.log("内容")
              }

              let fun = function(){
                  console.log("内容")
              }

              fun()
              let fun = new Function('console.log("内容")')
              

              补充函数内存结构

                函数销毁的执行空间

              函数不被销毁的执行空间

了解闭包

闭包是javascript语法现象,是函数的高级用法

            闭包形成条件:

                1. 函数嵌套- 外层函数 内层函数

                2. 外部引用返回的内层函数

                3. 内层使用外层函数变量

            闭包作用:

                1. 形成不被销毁的执行空间,延长变量生命周期, 缺点,容易引起内存泄露

                2. 外部可以访问内部函数的变量- 变量作用域扩展 - 没有形成闭包,只能内部函数访问外层函数变量

                3. 形成块作用域定义私有变量 

闭包三种写法

image.png

闭包的特点

image.png

闭包的应用

image.png

柯里化函数

  将有多个形参的函数转换成多个只有一个形参的函数

            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. 

image.png

image.png

image.png

柯里化日志工具函数

/**

			 * 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()

构造函数继承

image.png

原型拷贝继承

image.png

示例

image.png

image.png

原型继承

// 父类

			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__);

image.png

组合继承

image.png

image.png

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);