最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 彻底弄懂JavaScript 面向对象编程

    正文概述 掘金(幽蝉)   2020-12-30   310

    面向对象编程

    面向对象是一种编程思想,经常被拿来和面向过程比较。

    简单点,面向过程关注的重点是动词,是分析出解决问题需要的步骤,然后编写函数实现每个步骤,最 后依次调用函数。而向对象关注的重点是主谓,是把构成问题的事物拆解为各个对象,而拆解出对象的目的也 是为了实现某个步骤, 而是为了描述这个事物在当前问题中的各种行为。

    面向对象的特点:

    1、封装 让使用对象的人不考虑内部实现,只考虑功能使用把内部的代码保护起来,只留出一些api接口供用户使用。

    2、继承 就是为了代码的复用,从父类上继承出一些方法和属性,子类也有自己的一些属性

    3、多态 是不同对象作用于同一操作产生不同的效果。多态的思想实际上是把“想做什么”和“谁去做”分开

    什么时候适合使用面向对象

    可以看出来,在比较复杂的问题面前,或者参与方较多的时候,面向对象的编程思想可以很好的简化问题,并且能够更好的扩展和维护。

    Js中的面向对象

    对象包含方法和属性

    创建对象

    1、普通方式

    const Player = new Obejct();
    Player.color = "white"
    Player.start = function() {
      console.log('start')
    }
    
    

    工厂模式

    function createObject() {
      const Player = new Obejct();
      Player.color = "white"
      Player.start = function() {
        console.log('start')
      }
      return Player
    }
    

    2、构造函数/实例

    通过 this 添加的属性和 法总是指向当前对象的,所以在实例化的时候,通过this添加的属性和方法都会在内存中复制一份,这样就会造成内存的浪费。

    但是这样创建的好处是即使改变了某一个对象的属性或方法,不会影响其他的对象(因为每 个对象都是复制的一份)

    function Player(color) {
      this.color = color
      this.start = function() {
        console.log(color)
      }
    }
    
    const player1 = new Player('red')
    const player2 = new Player('blue')
    
    console.log(player1 === player2) // false 内存被创建了多次
    

    3、原型

    通过原型继承的方法并不是自身的,我们要在原型链上一层一层的查找,这样创建的好处是只在内存中创建一次,实例化的对象都会指向这个prototype对象。

    function Player(color) {
      console.log(color)
    }
    Player.prototype.start = function() {
      console.log(color)
    }
    const player1 = new Player('red')
    const player2 = new Player('blue')
    console.log(player1.start === player2.start) // true
    

    4、静态属性 是绑定在构造函数上的属性方法,需要通过构造函数访问

    function Player(color) {
      this.color = color
      if (!Player.total) {
      	Player.total = 0
      }
      Player.total++
    }
    
    const player1 = new Player('red')
    console.log(Player.total)
    const player2 = new Player('blue')
    console.log(Player.total)
    

    原型及原型链

    function Player(color) {
      console.log(color)
    }
    Player.prototype = {
      start: function() {
      	console.log('start')
      },
      revert: function() {
      	console.log('revert')
      }
    }
    
    找Player的原型对象
    
    const Player1 = new Player('red')
    const Player2 = new Player('blue')
    
    console.log(Player1.__proto__) // === Player.prototype {start: ƒ, revert: ƒ}
    console.log(Object.getPrototypeOf(Player1)) // Player.prototype  {start: ƒ, revert: ƒ}
    
    Object.getPrototypeOf  获取__proto__
    
    console.log(Player.__proto__)  // [Function]
    

    流程图 彻底弄懂JavaScript 面向对象编程

    new关键字

    • 一个继承自Player.prototype的新对象Player1被创建
    • Player1.proto指向Player.prototype
    • 将this指向新创建的对象Player1
    • 返回新对象
    • 如果构造函数没有显式返回值,则返回this
    • 如果构造函数有显式返回值,是基本类型, 如 number,string,boolean, 那么还是返回this
    • 如果构造函数有显式返回值,是对象类型, 如{ a: 1 }, 则返回这个对象{ a: 1 }
    function proPlayer() {
        return {a: 1}
    }
    const pro1 = new proPlayer()
    console.log(pro1) // {a: 1}
    
    function proPlayer() {
        return 123
    }
    const pro1 = new proPlayer()
    console.log(pro1) // proPlayer {}
    
    function proPlayer() {
        return
    }
    const pro1 = new proPlayer()
    console.log(pro1) // proPlayer {}
    
    

    实现new

    function objectFactory() {
      let obj = new Object();
      let Constructor = [].shift.call(arguments)
      obj.__proto__ = Constructor.prototype
      let result = Constructor.apply(obj, arguments)
      return typeof result === "object" ? result : obj;
    }
    

    原型链

    我们都知道当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还 查不到,就去找原型的原型,一直找到最顶层为止。

    function Player() {}
    Player.prototype.name = 'Tom'
    let p1 = new Player()
    p1.name = 'Davi'
    console.log(p1.name) // Davi
    delete p1.name
    console.log(p1.name) // Tom
    如果我们在Player.prototype中也找不到name属性的化,就会去Player.prototype.__proto__中寻找,也就是{}
    
    delete Player.prototype.name
    console.log(p1.name)
    

    继承

    1、原型链继承

    function Parent() {
      this.name = 'parentName'
    }
    Parent.prototype.getName = function() {
      console.log(this.name)
    }
    function Child() {}
    Child.prototype = new Parent()
    Child.prototype.constructor = Child
    
    let child1 = new Child()
    child1.getName()
    

    缺点:

    1、如果有属性是引用类型,一旦某个实例修改了这个属性,所有实例都会收到影响

    2、创建实例的实例的适合,不能传参

    function Parent() {
      this.actions = ['parentName', 'play']
    }
    function Child() {}
    Child.prototype = new Parent()
    Child.prototype.constructor = Child
    let child1 = new Child()
    let child2 = new Child()
    child1.actions.pop()
    console.log(child1.actions) //parentName
    console.log(child2.actions) //parentName
    

    2、构造函数

    
    function Parent(name, actions) {
      this.actions = actions;
      this.name = name;
      this.eat = function() {
      	console.log(name)
      }
    }
    function Child(id, name, actions) {
      Parent.call(this, name); // 如果想直接传多个参数, 可以Parent.apply(this, 		Array.from(arguments).slice(1));
      this.id = id;
    }
    const child1 = new Child(1, "c1", ["eat"]);
    const child2 = new Child(2, "c2", ["sing", "jump", "rap"]);
    
    console.log(child1.name); // { actions: [ 'eat' ], name: 'c1', id: 1 }
    console.log(child2.name);
    console.log(child1.eat === child2.eat)
    

    缺点:浪费内存

    组合继承

    function Parent(name, actions) {
        this.name = name;
        this.actions = actions;
    }
    Parent.prototype.eat = function () {
        console.log(`${this.name} - eat`);
    };
    
    function Child(id) {
      Parent.apply(this, Array.from(arguments).slice(1));
      this.id = id;
    }
    
    Child.prototype = new Parent();
    Child.prototype.constructor = Child;
    function Child(id) {
       Parent.apply(this, Array.from(arguments).slice(1));
       this.id = id;
    }
    Child.prototype = new Parent();
    Child.prototype.constructor = Child;
    

    缺点: 调用了两次构造函数

    寄生式组合继承

    function Parent(name, actions) {
        this.name = name;
        this.actions = actions;
    }
    Parent.prototype.eat = function () {
        console.log(`${this.name} - eat`);
    };
    
    function Child(id) {
      Parent.apply(this, Array.from(arguments).slice(1));
      this.id = id;
    }
    
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
    const child1 = new Child(1, "c1", ["hahahahahhah"]);
    const child2 = new Child(2, "c2", ["xixixixixixx"]);
    
    
    
    
    
    
    

    起源地下载网 » 彻底弄懂JavaScript 面向对象编程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元