面向对象 && 原型链 你必须得会!

275 阅读4分钟
  • 面向对象: 是一种编程思想;OOP; java c++ php python JS 类的'继承 封装 多态'
  • 面向过程:也是一种编程思想
 比如     类(类型)        实例(具体的某个东西)
          人类                马云
          动物类              人类
          猴类                孙悟空
  
  JS中的内置类:'Array数组类         []
                String字符串类       ''
                Number数字类         NaN
                Boolean布尔类        true  false
                Object基类           {}
                Function函数类       function(){}
                ...                  ...

创建实例的两种方式

var ary =['1','2']  //字面量的方式创建的数组类的实例
var ary2=new Array('1','2')  //构造函数的方式创建的数组类的实例  new出来的都是引用数据类型
var ary3=new Array(10) //参数只有一个数字的时候  数字代表数组的长度

JS中常见的设计模式

  • 单例模式
  • 工厂模式
  • 构造函数模式
  • 原型模式

单例模式

单例模式就是一个对象;可以避免命名冲突的问题;对象名 我们也称为命名空间 可以用来封装一些函数库

            var name = '小明'
            var age = 10
            var sex = '男'
            var eat = function(){}
            var play = function(){}

var per1 = function(){
    name:'小明'
    age : 10
    sex : '男'
    eat : function(){}
    play : function(){}
}
var per2 = function(){
    name:'小红'
    age : 15
    sex : '女'
    eat : function(){}
    play : function(){}
}

高级单例模式:也是一个对象; 只是由一个函数返回了一个单例; 可以用来模块化开发

function fn(){
    var name = '小明'
    var age = 10
    function init(){
        console.log(name,age)
    }
    return {
        init
    }
}
//再来看这道题
var obj2 = (function(){
        var name = 222;
        var age = 333;
        function f(){
            console.log(name,age)
        }
        function changeAge(n){
            age = n;
        }
        return {
            name,
            age,
            f,
            changeAge
        }
    })()
    obj2.name = 666;
    obj2.changeAge(100)
    obj2.f() // 222   100
    console.log(obj2.name,obj2.age)// 666  333

工厂模式

工厂模式: 多用于创建多个含有相同属性,和方法的对象,避免代码的重复编写; 批量产生单例

 function factory(name,age,sex){
     var obj={
         name,age,sex,
         eat(){
             
         }
         play(){
             
         }
     }
 }
 var par=factory('小明',10,1)

构造函数模式

构造函数模式:一般用来写一些插件

function Person(name,age,sex){
    this.name=name
    this.age=age
    this.sex=sex
    this.eat=function(){}
    this.play=function(){}
}
var per1 = new Person('小明',100,0)  //per1是Person的一个实例
//new 执行函数的时候,开辟作用域 形参赋值 变量提升;然后把函数中的this 指向了一个新开辟的堆内存,在这之后,再去操作this的时候,其实就是在造作这个堆内存最后把 this 返出去;
//若写了返回值 但是返回的是一个值类型 那么默认返回值仍然是this  若返回的是引用数据类型 则返回值会默认的返回值换掉

//es6的箭头函数是不能通过new的方式执行
//es6 创造类的方式 是通过class创造的
class fn3{
    constructor(name,age){
        this.name=name
        this.age=age
    }
}
var f3 = new fn3('小明',100)

原型模式

原型模式 : 在构造函数的基础上加一个原型(prototype)的概念

function Person(name='小明',age=10,sex=1){
    this.name=name
    this.age=age
    this.sex=sex
}
Person.prototype.eat=function(){
    console.log('吃')
}
Person.prototype.play=function(){
    console.log('玩')
}
var p1 = new Person()
var p2 = new Person()
console.log(p1,p2) //p1.eat===p2.eat  p1.play===p2.play

//es6的写法
class Fn{
    constructor(name,age){
        this.name=name
        this.age=age
    }
    //只能写函数 只能写简写  中间不能有标点符号
    eat(){}
    play(){}
}
//Fn 只能通过 new 的方式执行
var f =new Fn()

原型链

原型链:是属性的查找机制,现在自己身上查找,没有的话 通过__proyo__再去所属类的原型上查找,若所属类的原型上也没有该属性,则通过该原型的__proto__再去原型所属类的原型上接着查找,直到找到基类的原型上,在没有的话 就是undefined

原型重构

原型重构:只针对自定义类

缺点是原型重构身上没有constructor;解决方法:自己手动补一个constructor的指向

例题:

    function Person(name,age) {
       this.name = name;
       this.age = age;
   }
   Person.prototype.eat = function(){
       console.log('吃火锅')
   }
   var p = new Person('小红',100);
   Person.prototype = {
       constructor:Person,
       eat(){
           console.log('吃水果')
       },
       play(){
           console.log('玩游戏')
       }
   }
   var p1 =new Person('小明',20);
   p1.eat()  //吃水果
   p.eat();  //吃火锅

对于原型图的三句话

  • 每一个函数(类)都有一个默认的prototype指向自己的原型对象

  • 每一个实例(对象)都有一个__proto__的属性 指向所属类的原型对象

  • 每一个默认的原型对象上 都有一个constructor属性指向对应的构造函数本身

    如图所示👇