js的原型链以及继承

1. 先有构造函数,再有的实例对象
2. 构造函数里面有一个原型对象
3. 原型对象里面的构造器指向对应的构造函数
4. 实例对象里面的原型指向构造函数里面的原型对象

  原型链:是一种关系,实例对象和原型对象之间的关系,通过__proto __来联系的,构造函数本身与实例对象没什么联系
 
  构造函数里面的原型对象里面的原型__proto__指向的是objct,,objct的原型为null
 例如:
var divObj = document.getElementById("dv")
  console.dir(divObj);
var divObj = document.getElementById("dv")
    console.dir(divObj);
     
divObj.__proto__---->HTMLDivElement.prototype的__proto__----->
HTMLDivElement.prototype的__proto__----->Element.prototype的
__proto__----->Node.prototype的__proto__-------->
eventTarget.prototype的__proto__---->Object.prototype没有__proto__,
所以Object.prototype中的__proto__为null
 

this对象 

构造函数中的this是实例对象
严格模式:
"use strict";
function f1 () {
console.log(this) ;window
}
f1();   //当加上严格模式后f1()调用结果为undefined,Window.f1()才对
不加上严格模式,不用加Window
原型对象方法中的this也是实例对象


 


 

原型的指向改变

当原型对象prototype里面的指向改变了,那么原型__proto__指向也改变了
 这里的原型对象的指向相当于C语言中的指针

 先改变原型对象的指向,再添加方法,才能访问当前的方法

这里就相当于我告诉你钱在我这让你来拿,但是你来的途中,我说钱不在我这,所以你在我这拿不到钱,而如果先把钱移动的位置告诉你,你就可以直接拿到钱,是一个道理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
     function Person (age) {
        this.age = age;
    }
     Person.prototype.study = function () {
        console.log("学习很重要");
    }
     function Zhu () {
    }
    Zhu.prototype = new Person(10);  
     Zhu.prototype.eat = function () {//指向改变后,再给一个新的原型
        console.log("猪只知道吃");
    }
    var zhu = new Zhu();
//    var stu = new Person(10);
    zhu.study();
    zhu.eat();
</script>
</body>
</html>

继承

真正的面向对象语言存在类(class)(特殊的数据类型),js没有类的概念,不是面向对象的语言,所以js没有类,但是js可以模拟面向对象的思想编程,js中会通过构造函数来模拟类的概念


 继承:首先继承是一种关系,类与类之间的关系,js中没有类,但是通过构造函数模拟类,然后通过原型来实现继承
 继承也是为了数据共享,js中的继承也是为了实现数据共享

 原型作用之一:实现数据共享,节省空间
 原型作用之二:为了实现继承

1,通过构造函数原型对象来继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>

    //通过原型继承 ,虽然能继承,但是都是一样的属性与值
    function Person (name,age,sex) {
       this.name = name ;
       this.age = age ;
       this.sex = sex ;
    }
    Person.prototype.study = function () {
        console.log("学习");
    }
    function Stu (score) {
//        this.name = name ;
//        this.age = age ;
//        this.sex = sex ;
        this.score = score;
    }
    Stu.prototype = new Person("张",17,"男"); //使学生的指向改变成人,那么人里面的属性和方法都能共享
    Stu.prototype.study1 = function () {
        console.log("学习");
    }
    var stu = new Stu(100);
    var stu1 = new Stu(100);
    var stu2 = new Stu(100);
    stu.study();
    stu1.study();
    stu2.study();
    console.log(stu.name,stu.sex,stu.age,stu.score);
    console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
    console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
</script>
</body>
</html>

这个继承的缺点是所有继承的属性,方法都一样 

那么如何解决这种问题呢,来后接下来讲一讲下面这种继承

2,通过构造函数的借用继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
    //借用构造函数继承 :构造函数名字.call(当前对象,属性),解决了属性继承,并且值不重复,但是方法不能继承
    function Person (name,age,sex) {
        this.name = name ;
        this.age = age ;
        this.sex = sex ;
    }
    Person.prototype.study = function () {
        console.log("学习");
    }
    function Stu (name,age,sex,score) {
//        this.name = name ;
//        this.age = age ;
//        this.sex = sex ;
        Person.call(this,name,age,sex,score);//相当于调用Person对象
        this.score = score;
    }
//    Stu.prototype = new Person("张",17,"男");
    Stu.prototype.study1 = function () {
        console.log("学习");
    }
//    stu.name = "张";
//    stu.sex = "男";      在这里重新赋值就可以了,但是太多,而且这样就没有传值的必要性了
//    stu.age = "19";
//    var stu1 = new Stu(1);
    var stu1 = new Stu("张1","男1",119,1100);
//    stu1.name = "张1";
//    stu1.sex = "男1";
//    stu1.age = "20";
//    var stu2 = new Stu(1001);
    var stu2 = new Stu("张2","男2",129,1200);
//    stu2.name = "张2";
//    stu2.sex = "男2";
//    stu2.age = "21";
//    var stu3 = new Stu(1002);
    var stu3 = new Stu("张3","男3",139,1300);
//    stu3.name = "张3";
//    stu3.sex = "男3";
//    stu3.age = "22";
    console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
    console.log(stu2.name,stu2.sex,stu2.age,stu2.score);
    console.log(stu3.name,stu3.sex,stu3.age,stu3.score);
    stu3.study();   //报错,方法不能继承

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

这种方法虽然解决了属性值不用,但是缺陷在于其方法不能继承,调用方法,会报错 ,那么为了解决不报错问题,接下来引入

3.组合继承(原型与借用一起使用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
    function Person (name,age,sex) {
        this.name = name ;
        this.age = age ;
        this.sex = sex ;
    }
    Person.prototype.study = function () {
        console.log("学习");
    }
    function Stu (name,age,sex,score) {
        Person.call(this,name,age,sex,score);//相当于调用Person对象
        this.score = score;
    }
        Stu.prototype = new Person(); //不传值
    Stu.prototype.study1 = function () {
        console.log("学习");
    }
    var stu1 = new Stu("张1","男1",119,1100);
    var stu2 = new Stu("张2","男2",129,1200);
    var stu3 = new Stu("张3","男3",139,1300);
    console.log(stu1.name,stu1.sex,stu1.age,stu1.score);
    stu1.study();
    console.log(stu2.name,stu2.sex,stu2.age,stu2.score);
    stu2.study();
    console.log(stu3.name,stu3.sex,stu3.age,stu3.score);
    stu3.study();   
</script>
</body>
</html>

后面还有继承的方法,明日再来总结

猜你喜欢

转载自blog.csdn.net/qq_40281275/article/details/82793061