简述面向对象

类。每一个类都有一个属性原型 prototype function Person(){ this skin= 黄色

    // 类。每一个类都有一个属性原型'prototype'
    function Person(){
        this.skin='黄色'
        this.hair='黑头发'
        this.spack=function(){
            console.log('hello')
        }
    }
    //实例。每一个实例都有一个属性叫做隐式原型'__proto__',它和该实例的类的原型是一样的,所以实例的__proto__ === 类的prototype !
    // 这就是经常说的原型链
    var ming=new Person()//这就是类的一个实例,实例就是类的一个具体表现

    // 一
    function Obj(name){
        this.name=name
        console.log(this.name)
    }
    var p=new Obj(大黄)//当我们都通过new一个实例的时候,那么上面构造函数里的this的指向就是p这个实例

    // 二
    var two={
        name:'大黄',
        sayName(){
            console.log(this.name)//这里的this指向就是two这个对象
        }
    }
    two.sayName()
    // this在声明的时候并不能看出它到底指向谁,只要一执行它的时候就会知道它到底指向谁
    // 比如:
    function sayName(){
        console.log(this.name)
    }
    let p1={
        name:'m1',
        sayName
    }
    let p2={
        name:'m2',
        sayName
    }
    p1.sayName()//此时打印的就是'm1'
    p2.sayName()//此时打印的就是'm2'
    // 所以说只有在执行的时候才会知道this的指向到底是谁
    sayName()// 或者我们可以直接调用  此时this的指向就是全局,也就是window
    window.name='全局'//现在它打印出来的就是'全局'
    // 所以函数内部的this指向当前函数的执行环境(函数所挂靠的实例对象),如果没有挂靠,那它就会指向全局
    // 设定this的意义:同一个函数在不同的环境下执行会有不同的效果(多态)

    // 三. 修改this的指向 call、apply、bind
        function sayName(){
            console.log(this.name)
        }
        let p1={
            name:'m1',
            sayName
        }
        let p2={
            name:'m2',
        }
        p1.sayName()//此时打印的就是m1,但是我想让它打印m2,就是改变this的指向怎么办呢?我们可以用call(p2)
        p1.sayName.call(p2,x,x,x,)//此时打印的就是m2,call方法它接受的参数就是新的指向环境,call也有第二个参数。p1.sayName.call(p2,‘m3’)
        //注意此时p2里面并没有sayName这个函数,所以说call方法还有劫持的功能,让p2拥有了p1的方法
        apply
        p1.sayName.apply(p2,['m3','m4'])//apply和call基本是一样的,唯一区别就传参数时apply是放在数组里的,而call可以直接写
        
        bind
        p1.sayName.bind(p2,'m3')()//bind和call差不多但是它要在最后加一个小括号,它在执行时返回一个函数所以在后面加小括号来执行它
        //这三个方法在面试时被问到的几率还是挺大的,因为它们很有意思,它就像强盗一样可以劫持别人的东西,并且还能执行,传参数

        //es6创建一个类
        class Obj{//用class的方法创建
            constructor(){//构造函数
                this.name='大黄',//实例属性
                this.age=4
            }
            speak(){//成员方法,成员方法之间是通过this来沟通的
                console.log('他是个好人',this.name)//这样就能拿到上面的name
            }
            walk(){
                console.log('他一天走1万步')
            }
        }
        let huang=new Obj()//这里可以给构造函数传参数
        
        //继承 extends
        class myObj{
            constructor(){
                this.length=0
            }
            toString(){
                console.log('wo是xxxx')
            }
        }
        class myObj2 extends myObj{//这是第一步通过extends继承。
            constructor(){
                super()//调用super,此时myObj2也拥有了myObj的length和toString方法
            }
            myLength(){
                console.log(this.length)
            }
        }
        let arr=new myObj2()