原型对象

Posted 澎湃_L

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原型对象相关的知识,希望对你有一定的参考价值。

一、引入

1、JS是一门脚本语言,解释型语言、弱类型语言、基于对象的语言、动态型语言

2、继承(面向对象有三个特性:封装、继承、多态  )是指类与类之间的关系,JS中没有类的概念,JS中有构造函数的概念,是可以继承的,是基于原型

3、创建对象的三种方法:字面量、系统方法构造函数、自定义构造函数

   <script>
    //字面量
    var per1={
        name:"刘备",
        age:25,
        show:function(){
            console.log("双股剑");
        }
    }
    //系统方法构造函数创建对象
    var per2=new Object;
    per2.name="张飞";
    per2.age=23;
    per2.show=function(){
        console.log("丈八蛇矛");
    }
    //自定义构造函数创建对象
    function Person(name,age){
        this.name=name;
        this.age=age;
        this.show=function(){
            console.log("青龙偃月刀");
        }
    }
    var per3=new Person("关羽",24)
    </script>

4、工厂模式和自定义构造函数的区别

  • 共同点:都是函数、都可以创建对象、都可以传入参数
  • 工厂模式:函数名小写,有new,有返回值,new之后的对象是当前的对象,对象创建,直接调用函数
  • 自定义构造函数:函数名大写(首字母),没有new,没有返回值,this是当前对象,对象创建,通过new出来(实例化对象)
   <script>
    //自定义构造函数创建对象
    function Person(name,age){
        this.name=name;
        this.age=age;
        this.show=function(){
            console.log("青龙偃月刀");
        }
    }
    var per1=new Person("关羽",24);
    //工厂模式创建对象
    function creatObj(name,age){
            var obj= new Object;
            obj.name=name;
            obj.age=age;
            obj.show=function( ){
                console.log("青釭剑");
            }
            return obj;
    }
    var per2=new creatObj("赵云",29);

5、构造函数和实例函数之间的关系

  • 注意:使用console.dir可以查看结构
  • 实例对象是通过构造函数来创建的,创建的过程叫实例化
  • 实例化对象会指向自己的构造函数(暂时理解)
  • 判断对象是不是这个数据类型,可以通过构造器的方法(实例对象.构造器==构造器名字)或者instanceof(对象 instanceof 构造函数名字 ),推荐后者
   <script>
    function Person(name,age){
        this.name=name;
        this.age=age;
        this.show=function(){
            console.log("青龙偃月刀");
        }
    }
    var per=new Person("关羽",24);
    //查看结构---看下图
    console.dir(Person);//构造函数
    console.dir(per);//实例对象
    //判断对象是不是这个数据类型
    //方法一:
    console.log(per instanceof Person);//true
    //方法二:
    console.log(per.constructor==Person);//true
    </script>

6、构造函数创建对象带来的问题

  • 产生多个内存空间
    <script>
        //创建的两个实例对象的方法虽然相同,但是并不相等,如果创建的对象过多,就会使占用过多内存
        function Person(name,age){
            this.mame=name;
            this.age=age;
            this.eat=function(){
                console.log("吃饭");
            }
        }
        var per1=new Person("李白",44);
        var per2=new Person("杜甫",50);
        console.log(per1.eat==per2.eat);//false
    </script>
  • 可以通过使用命名函数方法解决,但是可能会有变量冲突
    <script>
        //通过使用命名函数方法解决,但是可能会有变量冲突-----最好引入原型
        function Person(name,age){
            this.mame=name;
            this.age=age;
            this.eat=myEat;
        }
        function myEat(){
            console.log("吃饭");
        }
        var per1=new Person("李白",44);
        var per2=new Person("杜甫",50);
        console.log(per1.eat==per2.eat);//true
    </script>
  • 所以最好引入原型来解决

二、原型对象

1、构造函数创建函数带来的问题,可以通过原型的方法解决-----原型的作用之一:可以实现数据共享,节省内存空间

2、通过原型来添加方法:构造函数.prototype.方法名=一个函数

   <script>
    function Person(name,age){
        this.mame=name;
        this.age=age;
    }
    Person.prototype.eat=function(){
            console.log("吃饭");
        }
    var per1=new Person("李白",44);
    var per2=new Person("杜甫",50);
    console.log(per1.eat==per2.eat);//true
    </script>

3、案例:点击按钮改变div样式(使用原型的方法)

4、什么是原型?

  • 实例对象中有个属性,__proto__,也是对象,叫原型,不是标准的属性,在IE8中可能不支持,主要给是给浏览器使用的
  • 构造函数中有个属性,prototype,也是对象,叫原型,是标准属性,主要给程序开发人员使用
  • 所以原型就是__proto__或者prototype,都是原型对象

5、构造函数、原型对象、实例对象之间的关系(画图)

  • 构造函数可以实例化对象,产生实例对象
  • 构造函数中有一个属性,prototype,是构造函数的原型对象
  • 构造函数的对象中有一个构造器(constructor)指向构造函数本身
  • 实例对象中的原型对象,__proto__,指向的是该构造函数的原型对象(prototype)
  • 构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的
  <script>
        //自定义构造函数
        function Person(name,age){
            this.age=age;
            this.name=name;
        }
        //通过原型添加方法
        Person.prototype.sayHi=function(){
            console.log("hello");
        }
        //实例化对象
        per=new Person("小明",20);
        console.dir(Person);
        console.dir(per);
    </script>

6、利用原型共享数据

  • 需要共享的数据可以写在原型中,可以是属性或者方法
  • 不影响共享的数据写在构造函数中,需要共享的数据写在原型中
    <script>
        //自定义构造函数
        function Student(name,age){
            this.name=name;
            this.age=age;
        }
        //通过原型添加相同的数据,实现共享
        Student.prototype.height="180cm";
        Student.prototype.weight="100kg";
        Student.prototype.sex="都是男的";
        
        //实例化对象
        stu1=new Student("关羽",30);
        stu2=new Student("刘备",31);
        stu3=new Student("张飞",29);
        console.log(stu1.height);//180cm
        console.log(stu2.weight);//100kg
        console.log(stu3.sex);//都是男的
    </script>

7、简单的原型写法

  • 格式:构造函数.prototype={  属性或者方法  }
  • 但是这种写法需要手动修改构造器的指向----constructor:构造函数名
   <script>
        //自定义构造函数
        function Student(name,age){
            this.name=name;
            this.age=age;
        }
        //通过原型添加相同的数据,实现共享
        //简单的原型写法(放进一个对象里)
        //但是必须要手动修改构造器的指向
        Student.prototype={
            constructor:Student,
            height:"180cm",
            weight:"100kg",
            sex:"都是男的"
        }
        
        //实例化对象
        stu1=new Student("关羽",30);
        stu2=new Student("刘备",31);
        stu3=new Student("张飞",29);
        console.log(stu1.height);//180cm
        console.log(stu2.weight);//100kg
        console.log(stu3.sex);//都是男的}
    </script>

8、原型中的方法是可以互相进行访问的

   <script>
        //自定义构造函数
        function Student(name,age){
            this.name=name;
            this.age=age;
        }
        //通过原型添加方法
        Student.prototype.eat=function(){
            console.log("吃饭");
        };
        Student.prototype.sleep=function(){
            console.log("睡觉");
            this.eat();//添加eat方法
        };
        Student.prototype.play=function(){
            console.log("玩球");
            this.sleep();//添加sleep方法
        };
        //实例化对象
        var per=new Student("小明",20);
        per.eat();//吃饭
        per.sleep();//睡觉 吃饭
        per.play();//玩球 睡觉 吃饭
    </script>

9、原型的层层搜索

  • 实例对象使用的属性或者方法,先在实例对象中找,找到了则直接使用
  • 找不到则去实例对象的__proto__指向的原型对象prototype中找,找到了使用
  • 找不到则报错