原型、原型链、继承

原型

Javascript规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。

作用

数据共享,节省内存空间

案例
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title</title>
  <script>
    function Person(name,age) {
      this.name=name;
      this.age=age;
    }
    //通过原型来添加方法,解决数据共享,节省内存空间
    Person.prototype.eat=function () {
      console.log("吃凉菜");
    };
​
    var p1=new Person("小明",20);
    var p2=new Person("小红",30);
    console.log(p1.eat==p2.eat);//true
​
    console.dir(p1);
    console.dir(p2);
​
    //实例对象中根本没有eat方法,但是能够使用,这是为什么?
  </script>
</head>
<body>
</body>
</html>

  

通过原型的方式修改标签样式
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title</title>
  <style>
    div {
      width: 300px;
      height: 200px;
      background-color: red;
    }
  </style>
</head>
<body>
<input type="button" value="显示效果" id="btn"/>
<div id="dv"></div>
<script src="common.js"></script>
<script>
​
  function ChangeStyle(btnObj, dvObj, json) {
    // this代指当前对象
    this.btnObj = btnObj;
    this.dvObj = dvObj;
    this.json = json;
  }
  ChangeStyle.prototype.init = function () {
    //点击按钮,改变div多个样式属性值
    // this代指当前对象
    var that = this;
    this.btnObj.onclick = function () {//按钮
        console.log(this)   // this:代指 this.btnObj
      for (var key in that.json) {
        that.dvObj.style[key] = that.json[key];
      }
    };
  };
​
​
  var json = {"width": "500px", "height": "800px", "backgroundColor": "blue", "opacity": "0.2"};
  var cs = new ChangeStyle(my$("btn"), my$("dv"), json);
  cs.init();//调用方法
​
  //点击p标签,设置div的样式
​
​
</script>
​
</body>
</html>

  

简单原型的案例

需要手动修改构造器的指向

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title</title>
  <script>
    function Student(name, age, sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
    }
    //简单的原型写法
    Student.prototype = {
      //手动修改构造器的指向
      constructor:Student,
      height: "188",
      weight: "55kg",
      study: function () {
        console.log("学习好开心啊");
      },
      eat: function () {
        console.log("我要吃好吃的");
      }
    };
​
    var stu=new Student("段飞",20,"男");
    stu.eat();
    stu.study();
    console.dir(Student);
    console.dir(stu);
      
  </script>
</head>
<body>
​
​
</body>
</html>

  

构造函数,原型,实例对象三者间的关系

构造函数

构造函数中有一个属性叫prototype,是构造函数的原型对象

构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数

原型

实例对象的原型对象(__proto__)指向的是该构造函数的原型对象

实例对象

构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的

 

实例对象属性方法的调用顺序

先在构造函数中找

构造函数中没有,调用原型中的属性和方法、

圆形中没有则报错

 

改变原型的指向(原型链)

原型指向可以改变 实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(__proto__)指向也会发生改变

原型的指向是可以改变的 实例对象和原型对象之间的关系是通过__proto__原型来联系起来的,这个关系就是原型链

//人的构造函数
    function Person(age) {
      this.age=10;
    }
    //人的原型对象方法
    Person.prototype.eat=function () {
      console.log("人的吃");
    };
    //学生的构造函数
    function Student() {
​
    }
    Student.prototype.sayHi=function () {
      console.log("嗨,小苏你好帅哦");
    };
    //学生的原型,指向了一个人的实例对象
    Student.prototype=new Person(10);
    var stu=new Student();
    stu.eat();
    stu.sayHi();

  

 

 

实例对象和原型对象中属性重名的问题

实例对象访问这个属性,应该先从实例对象中找,找到了就直接用

找不到就去指向的原型对象中找,找到了就使用

function Person(age,sex) {
      this.age=age;
      this.sex=sex;
    }
    Person.prototype.sex="女";
    var per=new Person(10,"男");
    console.log(per.sex);       // 男
​
    Person.prototype.sex="哦唛嘎的";            // 改变原型中的sex值
    per.sex="人";                            // 改变对象中sex的值
    console.dir(per);
​

  

 

 

继承

通过原型实现继承

构造函数的原型中添加要继承的对象,即可使用继承的方法

Student.prototype=new Person("小明",10,"男");

注:因为改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性的值都是一样的

只能调用对象的属性,重新赋值,才能改变初始化的数据

这种赋值方式很不方便

 function Person(name,age,sex) {
      this.name=name;
      this.sex=sex;
      this.age=age;
    }
    Person.prototype.eat=function () {
      console.log("人可以吃东西");
    };
    Person.prototype.sleep=function () {
      console.log("人在睡觉");
    };
    Person.prototype.play=function () {
      console.log("生活就是不一样的玩法而已");
    };
​
​
    function Student(score) {
      this.score=score;
    }
    //改变学生的原型的指向即可==========>学生和人已经发生关系
    // Student.prototype=new Person("小明",10,"男");   // 所有继承的都会有初始值
    Student.prototype=new Person(); // 只继承属性,不赋初始值
    Student.prototype.study=function () {
      console.log("学习很累很累的哦.");
    };
​
    //相同的代码太多,造成了代码的冗余(重复的代码)
​
    var stu=new Student(100);
    console.log(stu.name);
    console.log(stu.age);
    console.log(stu.sex);
    stu.eat();
    stu.play();
    stu.sleep();
    console.log("下面的是学生对象中自己有的");
    console.log(stu.score);
    stu.study();

  

借用构造函数继承

借用构造函数:构造函数名字.call(当前对象,属性,属性,属性....);

解决了属性继承,并且值不重复的问题

缺陷:

父级类别中的方法不能继承

function Person(name, age, sex, weight) {
      this.name = name;
      this.age = age;
      this.sex = sex;
      this.weight = weight;
    }
    Person.prototype.sayHi = function () {
      console.log("您好");
    };
    function Student(name,age,sex,weight,score) {
      //借用构造函数
      // >> 会引用Person中的内容
      // >> 一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。
      Person.call(this,name,age,sex,weight);
      this.score = score;
    }
    var stu1 = new Student("小明",10,"男","10kg","100");
    console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);
​
    var stu2 = new Student("小红",20,"女","20kg","120");
    console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);
​
    var stu3 = new Student("小丽",30,"妖","30kg","130");
    console.log(stu3.name, stu3.age, stu3.sex, stu3.weight, stu3.score);

  

组合继承

原型继承 + 借用用构造函数继承

//原型实现继承
    //借用构造函数实现继承
    //组合继承:原型继承+借用构造函数继承
​
    function Person(name,age,sex) {
      this.name=name;
      this.age=age;
      this.sex=sex;
    }
    Person.prototype.sayHi=function () {
      console.log("阿涅哈斯诶呦");
    };
    function Student(name,age,sex,score) {
      //借用构造函数:属性值重复的问题
      // >> 解决原型继承中:继承过来的属性值一样的问题
      Person.call(this,name,age,sex);
      this.score=score;
    }
    //改变原型指向----继承
    Student.prototype=new Person();//不传值,解决借用用构造函数继承中:父类级别的方法不能继承的问题
    Student.prototype.eat=function () {
      console.log("吃东西");
    };

  

 

 

posted @ 2020-12-25 13:54  minnersun  阅读(101)  评论(0编辑  收藏  举报