day19-原型和继承

函数的显示原型(prototype)

prototype 是函数内的一个对象空间(公共空间),每个函数都有一个,被称为显示原型,用于解决构造函数内存浪费(在调用方法时调用几次就会创建多少次内存空间)的问题。

  • prototype 这个空间会在预编译的时候进行开辟 (只开辟一次)
  • 利用 prototype 可以解决构造函数内存储的函数开辟多个内存空间的问题
  • prototype 里面的方法可以直接通过对应的 [实例对象.方法名] 来访问
  • 建议将对应的属性存入对应的构造函数,将对应的方法存入 prototype
        Object.prototype.test = () => {
            console.log('Objectd的test');
        }
        class Animal {
            constructor() {
                this.name = 'Animal来福'
            }
            run() {
                console.log('Animal跑起来');
            }
        }
        class Dog extends Animal {
            constructor() {
                super()
                this.color = 'Dog黑白灰'
            }
            say() {
                console.log('Dog叫汪汪');
            }
        }
        let dog = new Dog()
        let animal = new Animal()
        let obj = new Object()
        dog.say() // 实例对象.方法名
        dog.run()
        dog.test()
        console.log(dog); // Dog {name: 'Animal来福', color: 'Dog黑白灰'}

class的机制

  • 将 contructor 外部声明的函数自动加入到原型中

对象的隐式原型( __proto__ )

__proto__ 是对象的一个对象空间(实例对象也属于对象),他指向对应的构造函数的prototype,

原型链

  • 在 __proto__ 中寻找属性的过程形成的链子 被称为原型链 
  • 对象赋值不遵从原型链 (如果存在属性那么对应的就修改 如果没有就添加)

【示例】

        function Person() {
            console.log(111)
        }
        let person = new Person()
        console.log(Person.__proto__.__proto__.__proto__) //null

        //函数的 __proto__   ƒ () { [native code] } ==> Object ==> null
        console.log(person.__proto__) //Person的prototype 对象

        console.log(person.__proto__.__proto__) //对象的__proto__ (Object.prototype)


        console.log(person.__proto__.__proto__.__proto__) 
        //Object.prototype的__proto__==>null

        //  找到对应null结束 Person -- Object -- null
  • 模拟实现 instanceOf

instanceOf :(主要用于引用数据类型,基础值类型不可用)返回 true / false

  • 用于判断某个实例是否属于某构造函数
  • 在继承关系中用来判断一个实例是否属于它的父类型或者祖先类型的实例

语法:[对象] instanceof [构造函数]

特殊情况:

console.log(Number instanceof Number)  // false
console.log(String instanceof String)  // false
console.log(Fun instanceof Fun)        // false,这里Fun指的是函数
console.log(null instanceof Object)   
// false,null不具有任何对象的特性,也没有__proto__属性
        // instanceof模拟实现原型链查找
        function MyInstanceof(son, father) {
            while (son.__proto__) {
                son = son.__proto__
                if (son.constructor == father) {
                    return true
                }
            }
            return false
        }
        console.log(MyInstanceof(dog, Dog)); //true
        console.log(MyInstanceof(dog, Animal)); //true
        console.log(MyInstanceof(dog, Object)); //true
        // instanceof
        console.log(dog instanceof Dog); //true
        console.log(dog instanceof Animal); //true
        console.log(dog instanceof Object); //true
  • 模拟实现new关键词

        // 模拟实现new
        function fn() {
            this.name = name
        }
        function MyNew(fn) {
            let obj = {}
            obj.__proto__ = fn.prototype
            fn.call(obj)
            return obj
        }
        console.log(myNew(fn));

【一些内置对象里面的方法大部分是放在原型上】*

如:forEach、reduce、some、find等

模拟数组的高阶函数:forEach、find、findIndex、reduce、reduceRight、some...

  • forEach
        Array.prototype.MyForEach = function(callback) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            for (let i = 1; i < this.length; i++) {
                callback(this[i], i, this)
            }
        }
        new Array(1, 5, 3, 7, 9, 2, 1).MyForEach((v, i, arr) => {
            console.log(v, i, arr);
        })
  • find、findIndex
        // find返回第一个符合条件的值
        Array.prototype.MyFind = function(callback) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            for (var i = 0; i < this.length; i++) {
                if (callback(this[i], i, this)) {
                    return this[i]
                }
            }
        }
        let res = new Array(1, 5, 2, 4, 3, 6, 8, 6).MyFind((v, i, arr) => {
            return v > 5
        })
        console.log(res);
        // findIndex返回第一个符合条件的下标
        Array.prototype.MyFindIndex = function(callback) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            for (var i = 0; i < this.length; i++) {
                if (callback(this[i], i, this)) {
                    return i
                }
            }
            return -1
        }
        let res1 = new Array(1, 5, 2, 4, 3, 6, 8, 6).MyFindIndex((v, i, arr) => {
            return v > 5
        })
        console.log(res1);
  • reduce、reduceRight
         // reduce
        Array.prototype.MyReduce = function(callback, value) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            let index = 1
            let prev = this[0]
            if (value) {
                prev = value
                index = 0
            }
            for (; index < this.length; index++) {
                prev = callback(prev, this[index], index, this)
            }
            return prev
        }
        let res = new Array(1, 5, 2, 4, 3, 6, 8).MyReduce((prev, current, i, arr) => {
            return prev + current
        }, 5)
        console.log(res);
        // reduceRight
        Array.prototype.MyReduce = function(callback, value) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            let index = this.length - 2
            let prev = this[this.length - 1]
            if (value) {
                prev = value
                index = this.length - 1
            }
            for (; index >= 0; index--) {
                prev = callback(prev, this[index], index, this)
            }
            return prev
        }
        let res1 = new Array(1, 5, 2, 4, 3, 6, 8).MyReduce((prev, current, i, arr) => {
            console.log(prev, current, i, arr);
            return prev + current
        }, 5)
        console.log(res1);
  • some、every
        //every
        Array.prototype.MyEvery = function(callback) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            for (var i = 0; i < this.length; i++) {
                if (!callback(this[i], i, this)) {
                    return false
                }
            }
            return true
        }
        let res = new Array(1, 5, 2, 4, 3, 6, 8, 6).MyEvery((v, i, arr) => {
            return v > 5
        })
        console.log(res);
        // some
        Array.prototype.MySome = function(callback) {
            if (typeof callback != 'function') {
                throw new Error()
            }
            for (var i = 0; i < this.length; i++) {
                if (callback(this[i], i, this)) {
                    return true
                }
            }
            return false
        }
        let res1 = new Array(1, 5, 2, 4, 3, 6, 8, 6).MySome((v, i, arr) => {
            return v > 5
        })
        console.log(res1);

继承

class 继承实现 extends (es6):可以继承静态方法 *

         class Animal {
            constructor(name) {
                this.name = name
            }
        }
        class Dog extends Animal {
            constructor(name, color) {
                super(name)
                this.color = color
            }
        }
        let dog = new Dog('来福', 'pink')
        console.log(dog); //Dog {name: '来福', color: 'pink'}

构造函数的继承 (继承不了静态的方法和属性)

  • 原型链继承:将父类对象放在子类的原型链上

        缺点:因为不能进行初始化赋值的操作,所以继承父类的属性值为undefined;

                   子类的原型要写在原型继承之后,否则会被覆盖。

  • 对象冒充:将对应的父类构造函数当作普通函数执行,传入对应的子类构造函数中的 this

        缺点:获取不了父类原型上的内容

  • 组合继承:原型链继承 + 对象冒充

        缺点:会重复继承父类原型的属性和方法

  • 寄生组合继承:主要寄生原型(将父类原型对象加入到子类的原型上) + 对象冒充

        // 父类构造

        function Father(name, age) {

            this.name = name

            this.age = age

        }

        // 子类构造

        function Son(height) {

            this.height = height

        }

原型链继承 

Son.prototype = new Father()
let son = new Son(170)
console.log(son);
// Son {height: 170}
//      height: 170
//      [[Prototype]]: Father
//          age: undefined
//          name: undefined

对象冒充

         function Son(height, name, age) {
            Father.call(this, name, age)
            this.height = height
        }
        let son = new Son('170', 'tom', 50)
        console.log(son);
        // Son {name: 'tom',age: 50,height: '170'}
        //      age: 50
        //      height: "170"
        //      name: "tom" 
       

组合继承

        function Son(height, name, age) {
            Father.call(this, name, age)
            this.height = height
        }
        Son.prototype = new Father()
        let son = new Son('170', 'tom', 50)
        console.log(son)
        // Son {name: 'tom',age: 50,height: '170'}
        //      age: 50
        //      height: "170"
        //      name: "tom" [
        //      [Prototype]]: Father
        //          age: undefined
        //          name: undefined

寄生组合继承

        function Son(height, name, age) {
            Father.call(this, name, age)
            this.height = height
        }
        Son.prototype = Object.create(Father.prototype)
        let son = new Son('170', 'tom', 50)
        console.log(son instanceof Son); //true
        console.log(son);
        // Son {name: 'tom',age: 50,height: '170'}
        //     age:50
        //     height:"170"
        //     name:"tom" 
        //     [[Prototype]]:Father
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值