原型链、面向对象

一、原型链

对于原型链,会从创建对象的方式、原型、构造函数、实例、原型链、instanceof 的原理、new 运算符这几个方面分析
对于创建对象的方式,如下所示:

  • 字面量的方式,如下所示:
  var o1 = {name: 'o1'};
  var o2 = new Object({name: 'o2'});

  • 构造函数的方式,如下所示:
  var M = function (name) { this.name = name; };
  var o3 = new M('o3');

  • Object.create 的方式,如下所示:
  var p = {name: 'p'};
  var o4 = Object.create(p);

对于原型、构造函数、实例、原型链这几个的关系,如下所示:

  • 在 JavaScript
    中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype
    属性,这个属性指向函数的原型对象,使用原型对象的好处是所有对象实例共享它所包含的属性和方法
  • 原型链解决的主要是继承问题。每个对象拥有一个原型对象,通过 proto
    指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向
    null(Object.proptotype.proto 指向的是null)。这种关系被称为原型链(prototype
    chain),通过原型链一个对象可以拥有定义在其他对象中的属性和方法
  • prototype 是构造函数的属性,proto 是每个实例都有的属性,可以访问 [[prototype]] 属性,实例的
    proto 与其构造函数的 prototype 指向的是同一个对象
  • 原型链是原型对象创建过程的历史记录,当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__
    隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构
  • 所有函数的__proto__都是指向Function的prototype,构造函数new出来的对象__proto__指向构造函数的prototype,非构造函数实例化出的对象或者对象的prototype的__proto__指向Object的prototype,Object的prototype指向null
  • 对于 instanceof的原理,instanceof主要用于判断某个实例是否属于某个类型,也可用于判断某个实例是否是其父类型或者祖先类型的实例。instanceof主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false。
    对于 new 运算符,如下所示:
  • 一个新对象被创建,它继承自 foo.prototype
  • 构造函数 foo 被执行,执行的时候,相应的参数会被传入,同时上下文 this 会被指定为这个新实例。new foo 等同于 new
    foo(),只能用在不传递任何参数的情况
  • 如果构造函数返回了一个对象,那么这个对象会去取代整个 new 出来的结果。如果构造函数没有返回对象,那么 new
    出来的结果为步骤一创建的对象

对于原型链的代码,如下所示:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>原型链</title>
  </head>
  <body>

    <script type="text/javascript">
     
      M.prototype.say = function () {
          console.log('say hi');
      };
      var o5 = new M('o5');


      var new2 = function (func) {
          var o = Object.create(func.prototype);
          var k = func.call(o);
          if (typeof k === 'object') {
              return k;
          } else {
              return o;
          }
      };

    </script>
  </body>
</html>


二、面向对象

对于面向对象,分为类与实例和类与继承,类与实例包括类的声明、生成实例,类与继承包括实现继承和继承的几种方式。
对于类的声明,如下所示:

  • 类的声明,代码如下
var Animal = function () {
    this.name = 'Animal';
};


  • es6 中 class 的声明

class Animal2 {
    constructor () {
        this.name = 'Animal2';
    }
}

对于类与继承的实现及方式,如下所示:

  • 借助构造函数实现继承,但是缺点是 child1 没有继承 Parent1 原型对象的方法,代码如下所示:
  function Parent1 () {
      this.name = 'parent1';
  }
  Parent1.prototype.say = function () {

  };
  function Child1 () {
      Parent1.call(this);
      this.type = 'child1';
  }
  console.log(new Child1(), new Child1().say());

  • 借助原型链实现继承,但是缺点是 s1 改变的东西,s2 也会看到,代码如下所示:
  function Parent2 () {
      this.name = 'parent2';
      this.play = [1, 2, 3];
  }
  function Child2 () {
      this.type = 'child2';
  }
  Child2.prototype = new Parent2();

  var s1 = new Child2();
  var s2 = new Child2();
  console.log(s1.play, s2.play);
  s1.play.push(4);

  • 组合方式,Parent3 初始化了两次,指向 Parent3 构造函数,代码如下所示:
  function Parent3 () {
      this.name = 'parent3';
      this.play = [1, 2, 3];
  }
  function Child3 () {
      Parent3.call(this);
      this.type = 'child3';
  }
  Child3.prototype = new Parent3();
  var s3 = new Child3();
  var s4 = new Child3();
  s3.play.push(4);
  console.log(s3.play, s4.play);

  • 组合继承的优化一,但是缺点是指向 Parent4 的构造函数,无法区分实例是由父类创建的,还是子类创建的,代码如下所示:
  function Parent4 () {
      this.name = 'parent4';
      this.play = [1, 2, 3];
  }
  function Child4 () {
      Parent4.call(this);
      this.type = 'child4';
  }
  Child4.prototype = Parent4.prototype;
  var s5 = new Child4();
  var s6 = new Child4();
  console.log(s5, s6);

  console.log(s5 instanceof Child4, s5 instanceof Parent4);
  console.log(s5.constructor);

  • 组合继承的优化二,代码如下所示:
  function Parent5 () {
      this.name = 'parent5';
      this.play = [1, 2, 3];
  }
  function Child5 () {
      Parent5.call(this);
      this.type = 'child5';
  }
  Child5.prototype = Object.create(Parent5.prototype);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值