面向对象基础二

一、基础知识复习

实例对象的_proto_和构造函数的prototype的指向是相同的。

实例对象中的_proto_是原形,浏览器使用的

构造函数中的prototype是原形是给程序员使用的

下面介绍的原型链是一种关系,是实例对象和原形对象之间的关系。关系是通过_proto_来联系的。

二、原形的指向_proto_最终指向了哪里?

    实例对象中有__proto__原型
     构造函数中有prototype原型
    prototype是对象
    所以,prototype这个对象中也有__proto__,那么指向了哪里
    实例对象中的__proto__指向的是构造函数的prototype

    所以,prototype这个对象中__proto__指向的应该是某个构造函数的原型prototype,最终指向的是object.prototype 是null

 function Person() {


    }
    Person.prototype.eat=function () {
      console.log("吃东西");
    };


    var per=new Person();
    console.dir(per);
    console.dir(Person); 

   console.log(per.__proto__==Person.prototype);

    console.log(per.__proto__.__proto__==Person.prototype.__proto__);
    console.log(Person.prototype.__proto__==Object.prototype);

    console.log(Object.prototype.__proto__);

三、实例对象和原形对象属性重名的问题

JS是一种动态类型的语言,对象要有什么直接点语法添加就可以。如果没有这个属性,直接 对象.属性名字就有了。如果没有赋值是undefined;

如果想改变原形对象中的属性,需要的格式是:  原形对象.属性=值; Person.prototype.sex="哦唛嘎的" per.sex="人";//这样只能够改变自己的属性值,不能改变原形中的属性值。

 function Person(age,sex) {
      this.age=age;
      this.sex=sex;
    }
    Person.prototype.sex="女";
    var per=new Person(10,"男");
    console.log(per.sex);
    //因为JS是一门动态类型的语言,对象没有什么,只要点了,那么这个对象就有了这个东西,没有这个属性,只要对象.属性名字,对象就有这个属性了,但是,该属性没有赋值,所以,结果是:undefined
    console.log(per.fdsfdsfsdfds);//是undefine 因为JS是一种动态类型语言,只要用点语法就有了。如果没有赋值是undefined
    

    console.log(fsdfdsfds);//由于当成一个变量输出,报错。

Person.prototype.sex="哦唛嘎的";

四、继承

1.原型链:是实例对象和原形对象之间的关系,通过_proto_来联系。

<script>
  var divObj=document.getElementById("dv");
  console.dir(divObj);
//divObj.__proto__---->HTMLDivElement.prototype的__proto__--->HTMLElement.prototype的__proto__---->Element.prototype的__proto__---->Node.prototype的__proto__---->EventTarget.prototype的__proto__---->Object.prototype没有__proto__,所以,Object.prototype中的__proto__是null
</script>

2.继承前奏

面向对象编程思想:根据需求,分析对象,找到对象有什么特征和行为,通过代码的方式来实现需求,要想实现这个需求,就要创建对象,要想创建对象,就应该显示有构造函数,然后通过构造函数来创建对象.,通过对象调用属性和方法来实现相应的功能及需求,即可
首先JS不是一门面向对象的语言,JS是一门基于对象的语言,那么为什么学习js还要学习面向对象,因为面向对象的思想适合于人的想法,编程起来会更加的方便,及后期的维护....

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

面向对象的特新:继承、封装、多态。

* 封装:就是包装
    * 一个值存储在一个变量中--封装
    * 一坨重复代码放在一个函数中--封装
    * 一系列的属性放在一个对象中--封装
    * 一些功能类似的函数(方法)放在一个对象中--封装
    * 好多相类似的对象放在一个js文件中---封装
    *
    * 继承: 首先继承是一种关系,类(class)与类之间的关系,JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承
    * 继承也是为了数据共享,js中的继承也是为了实现数据共享
    *
    * 原型作用之一:数据共享,节省内存空间
    * 原型作用之二:为了实现继承
    *
    * 继承是一种关系:
    *
    * 父类级别与类级别的关系
    *
    * 例子:
    *
    * 小杨--->人, 姓名, 有钱, 帅, 有功夫--降龙十八掌
    * 小杨子-->人,
    * 继承:
    * 姓氏----继承
    * 外表----继承
    * 财产----继承
    * 功夫---继承
    *
    *
    * 人:  姓名, 性别, 年龄 ,吃饭, 睡觉
    *
    * 学生类别: 姓名, 性别, 年龄 ,吃饭, 睡觉 学习行为
    * 老师类别: 姓名, 性别, 年龄 ,吃饭, 睡觉 工资,教学行为
    * 程序员: 姓名, 性别, 年龄 ,吃饭, 睡觉 工资, 敲代码
    * 司机类别: 姓名, 性别, 年龄 ,吃饭, 睡觉 工资 开车
    *
    *
    * 动物类别:  体重, 颜色, 吃
    * 狗类别:   体重,颜色, 吃, 咬人
    * 二哈类别: 体重,颜色, 吃, 咬人 逗主人开心,汪汪,你好帅
    *
    *
    *
    *
    *
    *
    * 多态:一个对象有不同的行为,或者是同一个行为针对不同的对象,产生不同的结果,要想有多态,就要先有继承,js中可以模拟多态,但是不会去使用,也不会模拟,
 

    //例子:
    //人,都有姓名,性别,年龄, 吃饭, 睡觉, 玩
    //学生,都有姓名,性别,年龄, 成绩, 吃饭, 睡觉, 玩 ,学习的行为


    //js中通过原型来实现继承


    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.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();

3.继承的两种方式,一种是改变原形的指向。一种是直接调用父级的构造函数。

改变原形指向:

function Person (name,age,sex,height) {
  this.name=name;
  this.age=age;
  this.sex=sex;
  this.height=height;
 
  }
  Person.prototype.sayHai=function(){
  console.log("您好");
  }
 
  function Student(score){
  this.score=score;
  }
  Student.prototype=new Person("jack",20,"男","50kg");
  Student.prototype.eat=function(){
  console.log("我特别能吃");
  }
  var student=new Student();
 
  console.log(student.name,student.age);

  借用构造函数:构造含糊名字.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.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);

3.组合继承

所谓组合继承是综合上面两种继承方式:

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("吃东西");
    };
    var stu=new Student("小黑",20,"男","100分");

    console.log(stu.name,stu.age,stu.sex,stu.score);


4.拷贝继承

就是把一个对象中的属性和方法,复制到另一个对象中。

一种是改变地址指向的继承,这种继承只是在栈中创建一个变量指obj2指向内存中的obj1。并没有开辟新的内存空间。var obj2=obj1;

一种是创建一个新的对象,这种继承是在内存中重新开辟空间,然后两个对象引用的指针的指向相同。

 var obj1={
        name:"小糊涂",
        age:20,
        sleep:function () {
          console.log("睡觉了");
        }
      };
      var obj2={};
      for(var key in obj1){
        obj2[key]=obj1[key];
      }
      console.log(obj2.name);

5、总结继承

继承:
    
    * 原型作用: 数据共享 ,目的是:为了节省内存空间,
    * 原型作用: 继承  目的是:为了节省内存空间
    *
    * 原型继承:改变原型的指向
    * 借用构造函数继承:主要解决属性的问题
    * 组合继承:原型继承+借用构造函数继承
    * 既能解决属性问题,又能解决方法问题

    * 拷贝继承:就是把对象中需要共享的属性或者犯法,直接遍历的方式复制到另一个对象中

五、函数的角色

1.函数声明和函数表达式

 <script>
    //函数的角色:
    //函数的声明
    function f1() {
      console.log("我是函数");
    }
    f1();
    //函数表达式
    var ff=function () {
      console.log("我也是一个函数");
    };
    ff();

  </script>

2.函数中this指向

BOM中的顶级对象是window,浏览器中所有的东西都是window的。

* 普通函数中的this是谁?-----window
     * 对象.方法中的this是谁?----当前的实例对象
     * 定时器方法中的this是谁?----window
     * 构造函数中的this是谁?-----实例对象

     * 原型对象方法中的this是谁?---实例对象

//普通函数
          function f1() {
            console.log(this);
          }
         f1();


    //定时器中的this
          setInterval(function () {
            console.log(this);
          },1000);


    //构造函数
          function Person() {
            console.log(this);
    //对象的方法
            this.sayHi=function () {
              console.log(this);
            };
          }
    //原型中的方法
          Person.prototype.eat=function () {
            console.log(this);
          };
          var per=new Person();
          console.log(per);
          per.sayHi();
          per.eat();
    //BOM:中顶级对象是window,浏览器中所有的东西都是window的

3.函数中的不同的调用方式

普通函数的调用方式

构造函数的调用方式

//普通函数
    function f1() {
      console.log("文能提笔控萝莉");
    }
    f1();


    //构造函数---通过new 来调用,创建对象
    function F1() {
      console.log("我是构造函数,我骄傲");
    }
    var f=new F1();
    //对象的方法
    function Person() {
      this.play=function () {
        console.log("玩代码");
      };
    }
    var per=new Person();

    per.play();

六、函数和对象的关系

      所有的函数的源头是Function(){ } 所有的函数都可以看成是Function创建出来的实例对象

       函数是对象,对象不一定是函数。推理如下:

由于对象都存在_proto_原形,

函数中都存在prototype原形,

这两个原形都是什么?对象 Object类型

所以:函数中的prototype中存在_proto_原形

function F1() {
      }
      console.dir(F1);
      console.dir(Math);//中有__proto__,但是没有prorotype
      //对象中有__proto__,函数中应该有prototype

总结:如果一个东西里面有prototype,又有__proto__,说明是函数,也是对象


//所有的函数实际上都是Function的构造函数创建出来的实例对象

      var f1=new Function("num1","num2","return num1+num2");
      console.log(f1(10,20));
      console.log(f1.__proto__==Function.prototype);
     //  所以,函数实际上也是对象
      console.dir(f1);
     console.dir(Function);




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值