首页 > 其他分享 >面向对象回顾及原型讲解

面向对象回顾及原型讲解

时间:2022-08-17 20:33:46浏览次数:58  
标签:__ console log Person proto 面向对象 原型 讲解 prototype

面向对象回顾

            核心概念:万物皆对象 (顶层对象Object)抽取行为作为方法 抽取名词作为属性

        俩种构建对象的方式

            构造函数构建

                es6的形式 class                
                class Person{
                    constructor(){ //构造器
                        this.name = 'jack'
                    }
                }

 

                es3的形式 function                
                function Person(){
                    this.name = 'jack'
                }

 

                使用new关键词                
               var person = new Person()

 

  •  自动构建对象
  •  手动设置属性
  •  自动返回对象

            工厂构建

               
                 function factory(){
                    var obj = new Object()
                    obj.name = 'jack'
                    return obj
                }  

 

                调用方法               
                 var person = factory()

 

  •  手动构建对象
  •  手动设置属性
  •  手动返回对象  

prototype

            概述:所有的函数都拥有一个属性 这个属性称为prototype 他是一个对象空间(里面就可以存放对应的数据)他被称为显式原型

            示例

               
                function fn(){
                }
                //打印这个属性对应的空间
                console.log(fn.prototype)//  {constructor:f}
                constructor 构造器他指向对应的构建的函数(指向他自己)

 

                根据上面的我们可以看到每个函数都有这样的一个属性,那么作为构造函数他是不是也有对应prototype属性                
                function Person(){
                }
                console.log(Person.prototype) //作为一个属性存在 属性是唯一 也就是当前他只有一个
                prototype 属性的声明只会声明一次

 

                作为一个属性存在 属性是唯一 也就是当前他只有一个prototype 属性的声明只会声明一次                 因为当前这个属性 他对应的是一个对象空间,所以他里面的内容可以被更改和设置的                 那么我们就可以在这个里面存放一些内容                 
                function Person(){
                }
                Person.prototype.username = 'jack' //往这个对象空间存放一个属性 叫username
                Person.prototype.age = 18 //往这个对象空间存放一个属性 叫age
                Person.prototype.sayHello = ()=>{}
                console.log(Person.prototype)

 

                通过实例对象 来访问对应的prototype里面的属性                 //取出里面数据 因为构造函数是用于构建对象的 所以我们这个prototype的里面数据 是应该给实例对象去获取                 
                    var person = new Person()                                

 

                //访问原型中数据(构造函数的prototype里面的属性)实例对象.属性名                
               console.log(person.username);

 

                因为上面讲过 对应的prototype是作为构造函数的属性 而构造函数的他只声明一次 那么对应的prototype也只声明一次                 也就意味者 你每次拿到的prototype是一个 也就是说他里面存放的数据也只声明一次                
                var person1 = new Person()
                console.log(person1.sayHello == person.sayHello);//true

 

                由此可见 如果想对应的数据只声明一次的情况 我们可以放在原型里面

        总结

            一般把方法放在原型里面             把属性放在构造函数里面             
            function Son(){
                this.name = 'jack'
                this.age = 18
            }
            Son.prototype.print = function(){
                console.log(this); //指向当前的实例对象
                console.log(this.name); //指向当前的实例对象
            }
            new Son().print()

 

 __proto__

            概述:每个对象都有一个属性 叫做 __proto__ ,他也是一个内存空间,他指向对应的构造函数的prototype。称为隐式原型。    

            示例

                
                var obj = {}
                console.log(obj.__proto__)

 

 

 

            这个对象空间里面也可以存储对应的数据 这个 __proto__ ,他是每个对象都有的,那么实例对象也是个对象他同样也有。            
            function Person(){
            }
            let person = new Person()
            person.__proto__.username = 'jack'
            console.log(person.__proto__)
            //通过打印的结果 我们可以看到对应的里面的结果类似于我们的构造的prototype
            console.log(Person.prototype == person.__proto__) //ture

 

            从上述代码 大家可以看到对应的构造函数的prototype和对应的实例对象的 __proto__ 是相等,那么             也就证明了对应俩个内容其实是一个对象。那么我们就要明白 谁指向谁,从对应的先后顺序来看,我们             知道先有的构造函数再有的实例对象,所以对应的实例对象的 __proto__ 是指向对应的构造函数的             prototype。那么这个内容是不是就是对象访问原型的属性(所以他又被称为隐式原型),所以我们在             实际使用中并不会用到 __proto__ ,而是通过这个属性来访问对应的显式原型。

        总结

            实例对象 __proto__ 是指向对应构造函数的prototype             在实际使用中一般不会用 __proto__ ,是通过他来访问对应的prototype               从上可得对应的实例对象的 __proto__ 是指向构造函数的prototype,那么请问对应的函数是不是也是一个对象,他同样具备 __proto__ ,那么他的 __proto__ 指向谁,最终又指向谁?

 原型链  

            概述: 原型链其实就对应的寻找原型( __proto__ )的过程组成的一个链式结构,称为原型链。

            示例

               
                Object.prototype.hello = 'hello'
                class Person{
                    constructor(){
                        this.username = 'jack'
                    }
                }
                Person.prototype.age = 18
                class Son extends Person{
                    constructor(){
                        super()
                    }
                }
                Son.prototype.say = ()=>{}
                let son = new Son()
                //son的__proto__指向构造函数的原型 对应的Son这个构造函数的__proto__又指向了对应的父类的原型
                //对应的父类的构造的函数原型的__proto__指向了对应的Object的构造函数的原型
                //那么对应的Object的构造函原型的__proto__ 指向null 这个寻找的过程就称为原型链
                console.log(son.__proto__.__proto__.__proto__.__proto__);
                //那么接下来 我们又知道了对应的对象去访问原型的中属性 直接通过点的形式
                //又明白了作用域链 是一层一层向上找变量作用域
                //所以我们又可以通过原型链来找对应的属性 原型中的属性
                console.log(son.age); //18
                console.log(son.hello); //hello
                console.log(son.abc); //undefined    

 

 

 

            这个寻找的过程就称为原型链

            那么我想问请问对应的对象的属性赋值算不算原型链

            不是 不是 不是!!!!

            那么对象的属性赋值的操作有就覆盖 没有就添加

            1.找的到就覆盖这个值             2.找不到就添加这个属性

        利用原型来实现对应的底层源码

            实现对应的数组的高阶函数

                
                //find findIndex
                Array.prototype.myFind = function(fn){
                    //先遍历数组
                    for(var i=0;i<this.length;i++){
                        if(fn(this[i],i,this)){
                            return this[i]
                        }
                    }
                }
                Array.prototype.myFindIndex = function(fn){
                    var index = -1
                    //先遍历数组
                    for(var i=0;i<this.length;i++){
                        if(fn(this[i],i,this)){
                            index = i
                            break
                        }
                    }
                    return index
                }
                //map forEach
                Array.prototype.myMap = function(fn){
                    var result = []
                    //先遍历数组
                    for(var i=0;i<this.length;i++){
                        result.push(fn(this[i],i,this))
                    }
                    return result
                }
                Array.prototype.myForEach= function(fn){
                //先遍历数组
                    for(var i=0;i<this.length;i++){
                        fn(this[i],i,this)
                    }
                }  

 

 继承

            概述:继承属于面向对象的三大特性之一,面向对象的三大特性。封装 (抽取内容封装) 继承(子类继承父类)多态(重写 重载)             继承为子类继承父类的内容,子类可以拥有父类所有的非私有的属性及方法。

        继承的实现

            extends 关键词(class的继承)*(es6的)

               
                class Person{
                    constructor(){
                        this.username = 'jack'
                    }
                }
                class Son extends Person{
                    constructor(){
                        super()
                    }
                }
                console.log(new Son().username) //jack    

 

            原型继承(prototype赋值给需要继承的对象)

               
                 function Person(){
                    this.password = '123'
                }
                function Son(){
                }
                Son.prototype = new Person()
                console.log(new Son().password )//123

 

                组合继承 (原型+call改this指向)                
                //组合继承
                function Person() {
                    this.password = '123'
                }
                function Son() {
                    Person.call(this) //将person里面的this改成Son里面的this
                }
                Son.prototype = new Person()
                console.log(new Son().password) //123  

 

              对象冒充(改this指向 找不到原型上的内容(无法继承原型))              
                //对象冒充
                function Person() {
                    this.password = '123'
                }
                function Son() {
                    Person.call(this) //将person里面的this改成Son里面的this
                }
                let son = new Son()
                console.log(son.password); 

 

  

 多态

            概述:一个东西多种形态体现,(水 冰 水汽)。子类是父类多态的体现(基于继承的)。

            重写 子类重写父类的方法

               
                function Person(){
                    this.sayHello = ()=>{
                        console.log('你好')
                    }
                }
                function Son(){
                    this.sayHello = ()=>{
                        console.log('hello') //子类重写父类方法
                    }
                }
                Son.prototype = new Person()
                let son = new Son()
                son.sayHello() //hello   

 

            重载 同一个类里面有多个同名的方法(覆盖 js没有重载)

            重写应用

            基础拖拽类

               
                    class Touch {
                    constructor(ele) {
                        this.ele = ele
                        this.handlerDown()
                    }
                    handlerDown() {
                        this.ele.onmousedown = (e) => {
                            e = e || event
                            //记录的是鼠标在div里面的位置
                            //在mousedown里面记录按下的位置
                            this.x = e.offsetX
                            this.y = e.offsetY
                            this.handlerMove()
                            this.handlerUp()
                        }
                    }
                    handlerMove() {
                        document.onmousemove = (e) => {
                            e = e || event
                            //记录每次的位置 在document里面的位置
                            var currentX = e.pageX
                            var currentY = e.pageY
                            //并且设置div的位置
                            this.ele.style.left = currentX - this.x + "px"
                            this.ele.style.top = currentY - this.y + "px"
                        }
                    }
                    handlerUp() {
                        //给document添加mouseup事件
                        document.onmouseup = function () {
                            //清除对应的mousemove事件
                            document.onmousemove = null
                        }
                    }
                }
                var box = document.getElementById('box')
                new Touch(box)  

 

      

            固定拖拽

               
                    class FixedTouch extends Touch {
                    constructor(box, ele) {
                        super(ele)
                        this.box = box
                    }
                    handlerMove() {
                        document.onmousemove = (e) => {
                            e = e || event
                            //记录每次的位置 在document里面的位置
                            var currentX = e.pageX - getOffset(this.box).left
                            var currentY = e.pageY - getOffset(this.box).top
                            //范围判断
                            this.target = {
                                x: currentX - this.x,
                                y: currentY - this.y
                            }
                            if (this.target.x < 0) {
                                this.target.x = 0
                            }
                            if (this.target.y < 0) {
                             this.target.y = 0
                            }
                            if (this.target.x > this.box.clientWidth - this.ele.offsetWidth) {
                                this.target.x = this.box.clientWidth - this.ele.offsetWidth
                            }
                            if (this.target.y > this.box.clientHeight - this.ele.offsetHeight) {
                                this.target.y = this.box.clientHeight - this.ele.offsetHeight
                            }
                            //并且设置div的位置
                            this.ele.style.left = this.target.x + "px"
                            this.ele.style.top = this.target.y + "px"
                        }
                    }
                }    

 

            基于固定拖拽的放大镜

               
                    class Magnifier extends FixedTouch {
                    constructor(smallBox, bigBox) {
                        //调用父类构造
                        super(smallBox, smallBox.querySelector('.move'))
                        this.smallBox = smallBox
                        this.bigBox = bigBox
                        this.move = smallBox.querySelector('.move')
                        this.bigImg = bigBox.children[0]
                        this.init()
                        this.handlerHover()
                        //取消按下的事件
                        this.handlerDown = () => {}
                        //调用move
                        this.handlerMove()
                    }
                    init() {
                        //计算对应的move这个盒子的宽高
                        // 大的比大的等于小的比小的 bigImg/bigBox = box/move ==> bigImg/box ==bigBox/move
                        this.move.style.width = this.smallBox.clientWidth /
                        (this.bigImg.clientWidth / this.bigBox.clientWidth) + 'px'
                        this.move.style.height = this.smallBox.clientHeight /
                        (this.bigImg.clientHeight / this.bigBox.clientHeight) + 'px'
                        //先需要隐藏
                        this.move.style.display = 'none'
                        this.bigBox.style.display = 'none'
                    }
                    handlerHover() {
                        //移入移出
                        this.smallBox.onmouseenter = () => {
                            this.move.style.display = 'block'
                            this.bigBox.style.display = 'block'
                            //x y的属性值
                            this.x = this.move.clientWidth / 2,
                            this.y = this.move.clientHeight / 2
                        }
                        this.smallBox.onmouseleave = () => {
                            this.move.style.display = 'none'
                            this.bigBox.style.display = 'none'
                        }
                        //添加一个移动的事件
                        this.smallBox.onmousemove = () => {
                            //改变大盒子里面图片的位置
                            this.bigImg.style.left = -this.target.x * this.bigImg.clientWidth /
                            this.smallBox.clientWidth + 'px'
                            this.bigImg.style.top = -this.target.y * this.bigImg.clientHeight /
                            this.smallBox.clientHeight + 'px'
                        }
                    }
                }        

 

es6的模块化   (一个内容如果需要导入 必须先导出)

            import 导入             export 导出             es6的写法                
                <script type='module'></script>

 

            第一种写法

                export导出

                   
                     //对象
                    const obj = {
                        username:"jack",
                        password:'123'
                    }
                    //函数
                    const sayHello = ()=>{
                        console.log('hello');
                    }
                    //值
                    const message = '这个是一个信息'
                    //数组
                    const arr = [1,2,3,4]
                    //变量的接的数据 需要导出必须用{}
                    export {
                        obj,
                        sayHello,
                        message,
                        arr
                    }  

 

                import导入

                   
                     import {
                        obj,
                        sayHello,
                        message,
                        arr
                    } from './a.js' //解构
                    sayHello()
                    console.log(`obj`, obj);
                    console.log(`message`, message);
                    console.log(`arr`, arr); 

 

       

            第二种写法

                export 导出

                   
                    export const obj = {
                        username:"jack",
                        password:'123'
                    }
                    export const sayHello = ()=>{
                        console.log('hello');
                    }
                    export const arr = [1,2,3,4]
                    export const message = '这个是一个信息'    

 

                import 导入

                   
                    //* 表示所有的 as取别名(随便取)
                    import * as hello from './a.js'
                    hello.sayHello()
                    console.log(`obj`, hello.obj);
                    console.log(`message`, hello.message);
                    console.log(`arr`, hello.arr);    

 

            第三种写法

                export 导出

                   
                   export default {
                        obj,
                        sayHello,
                        message,
                        arr
                    }  

 

                import 导入

                   
                    import a from './a.js'
                    a.sayHello()
                    console.log(`obj`, a.obj);
                    console.log(`message`, a.message);
                    console.log(`arr`, a.arr);

 

        总结

            export 导出内容

                export const 对应的变量                 export default 对应的变量                 export {}

            import 导入内容

                import 变量名 from 文件地址 (所有的话 * 必须取别名 as)

标签:__,console,log,Person,proto,面向对象,原型,讲解,prototype
From: https://www.cnblogs.com/lkm7/p/16596639.html

相关文章

  • 原型 prototype __proto__
    原型概念:每一个构造函数天生自带一个属性为prototype对象,是一个对象数据类型,里面可以存放对应的数据称为显示原型且唯一一般把方法放在原型里,属性放在构造函数里当......
  • 面向对象——类与对象的关系
    类和对象的关系类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物对象是抽象概念的具体实例创建和初始化对象使用new关键字创建......
  • 面向对象——初识面向对象、回顾方法定义调用
    初识面向对象属性+方法=类对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象来分析整个系统。但是,具体到微观操作,让然需要面向过程的思路去处......
  • 面向对象编程(深入)
    1/*2面向对象的三个概念31、类:是一个抽象概念,是产生对象的一个容器42、对象(实例):是一个实体,由类产生出来的一个带有类属性和方法的实体。53、实例化:产......
  • [Python学习笔记]Python基础-12 面向对象编程_属性和方法
    内置属性可以使用内置函数dir查看一个对象支持的所有属性和方法,Python中存在很多的内置属性classPerson(object):def__init__(self,name,age)->None:......
  • [Python学习笔记]Python基础-13 面向对象编程_继承和多态
    继承面向对象的编程有三大特性封装:函数是对语句的封装类是对函数和变量的封装继承类和类之间可以人为,手动的建立父子关系父类的属性和方法,子类可以使用......
  • Java面向对象—封装、继承、多态
    Java面向对象—封装、继承、多态在对面向对象的特征进行分析之前,先让我们来了解一下什么是面向对象。面向对象与面向过程:面向过程:是一种以过程为中心的编程思想,面向过程......
  • Python3项目初始化5-->面向对象
    18、面向对象--类和实例属性创建一个类classPerSon(object):  def__init__(self,name,age):    self.name=name    self.age=age  def......
  • github 代码简单讲解
     github地址:https://github.com/lijiesheng/rabbitmq/tree/simplesimple模式分支1:simple-data-lose没有引入应答机制,只要消费者关闭,队列中的数据就......
  • JSTL讲解
    JSTL概念:JavaServerPagesTagLibraryJSP标准标签库是由Apache组织提供的开源的免费的jsp标签 <标签>作用:用于简化和替换jsp页面上的java代码使用步骤:导......