为什么会出现原型? 为了解决构造函数实例化对象时造成的内存空间浪费的问题。 原型的作用? 1.资源共享,节省内存空间 2.用于模拟继承 什么是原型? 构造函数.prototype --- 原型对象
为什么会出现原型?
为了解决构造函数实例化对象时造成的内存空间浪费的问题。
原型的作用?
1.资源共享,节省内存空间
2.用于模拟继承
什么是原型?
构造函数.prototype ---> 原型对象
实例化对象.__proto__ ---> 原型对象
function Person(name,age){ this.name=name; this.age=age; } var per=new Person("pap",10); console.log(per); console.log(Person); console.log(per.__proto__); console.log(Person.prototype);
为什么会出现两种表示原型对象的形式?
实例化对象中有一个属性是__proto__,该属性指向的是构造函数的原型对象
构造函数中有一个属性是prototype,该属性指向的也是构造函数的原型对象
===>因此,上述两行可以得到的结论是:构造函数.prototype==实例化对象.__proto__; // true
console.log(per.__proto__==Person.prototype); // true
原型的简单应用:
function Person(age,sex) { this.age=age; this.sex=sex; } //通过构造函数的原型添加一个方法 Person.prototype.eat=function () { console.log("明天中午吃完饭就要演讲,好痛苦"); }; var per=new Person(20,"男"); per.eat(); //明天中午吃完饭就要演讲,好痛苦
构造函数,实例对象,原型对象之间的关系
构造函数实例和初始化一个实例对象,原型对象用来添加公共的属性和方法.
每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.
实例化对象直接指向构造函数的内部.
构造函数可以实例化对象 * 构造函数中有一个属性叫prototype,是构造函数的原型对象 * 构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数 * 实例对象的原型对象(__proto__)指向的是该构造函数的原型对象 * 构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的
利用原型共享数据
function Student(name,age,sex) { this.name=name; this.age=age; this.sex=sex; } //所有学生的身高都是188,所有人的体重都是55 //所有学生都要每天写500行代码 //所有学生每天都要吃一个10斤的西瓜 //原型对象 Student.prototype.height="188"; Student.prototype.weight="55kg"; Student.prototype.study=function () { console.log("学习,写500行代码,小菜一碟"); }; Student.prototype.eat=function () { console.log("吃一个10斤的西瓜"); }; //实例化对象,并初始化 var stu=new Student("晨光",57,"女"); console.dir(Student); console.dir(stu);
【注意】原型在自己定义的时候需要添加构造器constructor
//简单的原型写法 --> 将属性和方法都写在一起 Student.prototype = { //手动修改构造器的指向 constructor:Student, height: "188", weight: "55kg", study: function () { console.log("学习好开心啊"); }, eat: function () { console.log("我要吃好吃的"); } };
什么是原型链?
原型链是一种关系,是对象和原型对象之间的关系,该关系是通过原型(__proto__)来联系的,如图: 原型链: instance1--> instance2 --> constructor2.prototype…-->Object.prototype 【注意】原型对象的指向是可以改变的,当构造函数的prototype指向改变后,实例对象的__proto__指向也会发生改变,如下图:【举个栗子】:
function Father(){ this.property = true; } Father.prototype.getFatherValue = function(){ return this.property; } function Son(){ this.sonProperty = false; } //继承 Father但是原型链也存在某些问题,例如下方: 为了数据共享,改变原型指向,做到了继承---通过改变原型指向实现的继承 ·缺陷:因为改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性的值都是一样的了,所以,这就是问题,因此,只能重新调用对象的属性进行重新赋值, ·解决方案:继承的时候,不用改变原型的指向,直接调用父级的构造函数的方式来为属性赋值就可以了------借用构造函数:把要继承的父级的构造函数拿过来,使用一下就可以了 如何使用借用构造函数? 借用构造函数:构造函数名字.call(当前对象,属性,属性,属性....); ·解决了属性继承,并且值不重复的问题 ·缺陷:父级类别中的方法不能继承 【举个栗子】
// Son.constructor指向的是Father Son.prototype = new Father();//Son.prototype被重写,导致Son.prototype.constructor也一同被重写 Son.prototype.getSonVaule = function(){ return this.sonProperty; } var instance = new Son(); alert(instance.getFatherValue());//true
function Father(){ this.colors = ["red","blue","green"]; } function Son(){ Father.call(this);//继承了Father,且向父类型传递参数 } var instance1 = new Son(); instance1.colors.push("black"); console.log(instance1.colors);//"red,blue,green,black" var instance2 = new Son(); console.log(instance2.colors);//"red,blue,green" 可见引用类型值是独立的
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); 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);