Javascript高级学习笔记2 -- 原型及原型链1

原型

通过原型来添加方法,解决数据共享,节省内存空间
需要数据共享,节省内存空间时使用
类名.prototype.方法名=function(){}

//为内置对象添加原型方法
        
/*        var arr = new Array(10,20,30,40,50);
        arr.join("|");
        console.log(arr);
        
        var str = new String("哦!guoguo");
        str.indexOf("g");
        console.log(str);
        
        var dt = new Date();
        dt.getFullYear();
        console.dir(dt);\
*/
        //实例中的方法如果没有,去创建该实例对象的构造函数的原型对象中找
        
        //为系统的对象的原型中添加方法,相当于在改源码
        String.prototype.myreverse=function(){
            for(var i=this.length;i>=0;i--){ //this为调用这个方法的实例对象
                console.log(this[i]);
            }
        }
        var str = "guoguo123";
        str.myreverse();
        
        //为Array内置对象的原型对象中添加方法
        Array.prototype.mySort = function(){
            for(var i=0;i<this.length-1;i++){
                for(var j=0;j<this.length-1-i;j++){
                    if(this[j]<this[j+1]){
                       var temp = this[j];
                        this[j]=this[j+1];
                        this[j+1]=temp;
                       }
                }
            }
        };
        
        var arr=[33,3,1,22,100];
        arr.mySort();
        console.log(arr);
        
        String.prototype.sayHi=function(){
            console.log(this+"哈哈我瘦了");
        }
        
        var hi = "guoguo";
        hi.sayHi();

实例对象中的__proto__属性,也是对象,叫原型,不是标准的属性,浏览器使用的
构造函数中有一个属性,prototype,也是对象,叫原型,标准属性,程序员使用的
   
原型--> __proto__或者是prototype都是原型
作用:共享数据,节省内存空间
通过构造函数创建实例对象
构造函数中的prototype属性指向自己的原型对象
原型对象中的constructor构造器指向自己的构造函数
实例对象中的__proto__属性指向构造函数中的原型对象
 
//什么样的数据是需要写在原型中的?
        //需要共享的数据就可以写在原型中
        //原型的作用之一:数据共享
        
        
        //属性需要共享,方法也需要共享
        //不需要共享的数据写在构造函数中,需要共享的写在原型中
        
        function Student(name,age,sex){
            this.name=name;
            this.age=age;
            this.sex=sex;
        }
        
        //所有学生的身高都是188,体重都是55
        //所有学生每天都写写500行代码
        //所有学生每天都要吃西瓜
        
        Student.prototype.height="188";
        Student.prototype.weight="55KG";
        Student.prototype.study=function(){
            console.log("学习写500行代码");
        };
        Student.prototype.eat=function(){
            console.log("吃西瓜");
        };
        
        //实例化对象并初始化
        var stu = new Student("果果",20,"男");
        console.dir(Student);
        console.dir(stu);
        
//        stu.eat();
//        stu.study();

总结:   
构造函数可以实例化对象
构造函数中有一个属性叫prototype,是构造函数的原型对象
构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的是自己所在的原型对象所在的构造函数
实例对象的原型对象(__proto__)指向的是该构造函数的原型对象
构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的

//构造函数
        function Person(sex,age){
            this.sex=sex;
            this.age=age;
        }
        //通过原型添加方法
        Person.prototype.sayHi=function(){
            console.log("你好");
        }
        var per = new Person("男",20);
        console.dir(per); //实例对象
        console.log(per.__proto__); //IE浏览器为undefined
        console.dir(Person); //构造函数
        
        //实例对象中有两个属性(这两个属性是通过构造函数获得的),__proto__这个属性,浏览器使用的
        //构造函数中并没有sex和age这两个属性
        
        /*
            实例对象中有两个属性,__proto__,也是对象,叫原型,不是标准的属性
            构造函数中有一个属性,prototype,也是对象,叫原型,标准属性,程序员使用的
            
            原型--> __proto__或者是prototype都是原型
                作用:共享数据,节省内存空间
        */

需要共享的数据就可以写在原型中
原型的作用之一:数据共享    
属性需要共享,方法也需要共享
不需要共享的数据写在构造函数中,需要共享的写在原型中
实例对象(构造函数)的方法,是可以相互调用的
原型对象中的方法,是可以相互调用的
 
实例对象使用的属性或者方法,先在实例中查找,找到了则直接使用,
找不到则去实例对象的__proto__指向的原型对象prototype中找,
找到了则使用,找不到则报错
 
原型对象中的方法,是可以相互调用的
 
原型链
原型指向可以改变
原实例对象的原型__proto__指向的是该对象所在构造函数的原型对象
构造函数的原型对象(prototype)指向如果发生改变了,实例对象的原型(__proto__)指向也会发生改变
原型的指向是可以改变的
实例对象和原型对象之间的关系是通过__proto__原型来联系的,这个关系就是原型链
        //使用对象 --->使用对象中的属性和对象中的方法,使用对象先要有构造函数
        //构造函数
        function Person(name,age){
            //属性
            this.name = name;
            this.age = age;
            //在构造函数中的方法
            this.eat = function(){
                console.log("吃榴莲");
            };
/*             this.sayHi = function(){
                console.log("guoguo");
            }; */

        };
        //添加共享的属性
        Person.prototype.sex="男";
        //添加共享的方法
        Person.prototype.sayHi = function(){
            console.log("guoguo");
        };
        //实例化对象,并初始化
        var per = new Person("小明",20);
        per.sayHi(); //实例对象可以直接访问原型对象的属性或方法
        /*如果想使用一些属性和方法,并且属性的值在每个对象中都是一样的,方法在每个对象中的操作都是一样的,
        那么为了共享数据,节省内存空间,是可以把属性和方法通过原型的方式进行赋值*/

        console.dir(per); //实例对象的结构
        console.dir(Person); //构造函数的结构

        //实例对象的原型__proto__和构造函数的原型prototype指向市相同的
        //实例对象中的__proto__原型指向的市构造函数的原型prototype
        console.log(per.__proto__ == Person.prototype);
        //实例对象中__proto__是原型
        //构造函数中的prototype是原型

        //原型链:是一种关系,实例对象和原型对象之间的关系,关系是通过原型(__proto__)来联系的

原型链指向改变:

//构造函数中的this就是实例对象
    //原型对象中的方法中的this就是实例对象
/*         function Person(age){
            this.age = age;
            console.log(this);
        };

        Person.prototype.eat = function(){
            console.log("上面是构造函数中的this");
            console.log(this);
            console.log("这是原型方法中的this");
        };
        var per = new Person(10);
        per.eat();
        console.log(per); */



/*         function Student(){};

        Student.prototype.study = function(){
            console.log("加油努力学习");
        };
        
        Student.prototype = {
            eat:function(){console.log("我没报错");}
        };

        var stu = new Student();
        // stu.study();  报错了
        stu.eat(); */

        //人的构造函数
        function Person(age){
            this.age = 10;
        };
        //原型对象的方法
        Person.prototype.eat = function(){
            console.log("我想吃饭");
        };

        //学生的构造函数
        function Student(){};
        //学生的原型方法
        Student.prototype.study = function(){
            console.log("你好,努力学习哦");
        };
        //学生的原型方法指向了一个人的实例对象
        Student.prototype = new Person(10);
        var stu = new Student();
        stu.eat();  //我想吃饭
        //stu.study(); 报错了、

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

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

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

原型的最终指向:

        function Person(){

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

        var per = new Person();
        console.dir(per);
        console.dir(Person);
        
        //实例对象中有__proto__原型
        //构造函数中有prototype原型
        //prototype是对象
        //prototype中也有__proto__
        //实例对象中的__proto__指向的是构造函数的prototype
        //所以,prototype这个对象中的__proto__指向的应该是某个构造函数的prototype

        //Person中的prototype中的__proto__
        console.log(Person.prototype.__proto__);

        //实例对象__proto__指向的是构造函数的原型对象
        //原型对象的__proto__指向Object的prototype
        //Object的Prototype的__proto__指向的是null

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

个人总结:

构造函数创建实例对象
构造函数的原型对象的构造器指向构造函数
实例对象及__proto__指向构造函数的原型
原型对象的prototype中的__proto__属性指向的是Object的prototype
而Object的prototype的__proto__指向的数null

猜你喜欢

转载自www.cnblogs.com/guoguolt/p/12577322.html