原型的作用是什么?
function Person(name,age){
this.name = name ;
this.age = age;
this.say = function(){
console.log('hello');
};
}
for(var i = 0 ; i<100 i++){
var per = new Person('张三',25);
console.log(per.name);
console.log(per.age);
per.say();
}
如果想要创建多个对象,并且它们每个属性的值都是一样的,方法也一样,用以上这中方法或许太过繁琐。
function Person(){}
Person.prototype.name = '张三';
Person.prototype.age = 25;
Person.prototype.sayHello=function(){
console.log('hello');
}
var per = new Person();
console.log(per);
console.log(per.age);
console.log(per.name);
console.log(per.sayHello);
为了共享数据,节省内存空间,我们可以通过以上这种原型的方式进行赋值。
原型链
通过查看结构发现:实例对象的原型__proto__和构造函数的原型prototype指向相同。
原型链:是一种关系,实例对象和原型对象之间的关系,这种关系是通过原型__proto__来联系的。
function Person(){}
//为Person添加原型方法eat
Person.prototype.eat=function(){
console.log("eat food");
}
function Student(){}
//为Student添加原型方法sayHi
Student.prototype.sayHi=function(){
console.log("hi");
}
//让学生的原型指向了人的实例对象
Student.prototype=new Person();
var stu =new Student();
// stu.sayHi(); //找不到sayHi方法了
stu.eat();
通过以上了解到:原型指向可以改变
实例对象的原型__proto__指向的是该对象所在的构造函数的原型对象
构造函数的原型对象(prototype)指向如果改变了,实例对象的原型(proto)指向也会改变
prototype也是对象,这个对象中的__proto__指向object这个构造函数的原型对象prototype
object构造函数中的原型对象prototype的__proto__是null
js中通过原型来实现继承
function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
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("ss",10,"男");
// Student.prototype.name='xxx' 可以像这样修改属性值
Student.prototype.study=function(){
console.log("学习");
};
var stu=new Student(100);
console.log(stu.name); //ss
console.log(stu.age); //10
console.log(stu.sex); //男
console.log(stu.score); //100
stu.eat();
stu.sleep();
stu.play();
stu.study();
为了数据共享,改变原型指向,做到了继承---通过改变原型指向实现的继承
缺陷:因为改变原型指向的同时实现继承,直接初始化了属性,继承来的属性值都一样
function Person(name,age,sex,weight){
this.name=name;
this.age=age;
this.sex=sex;
this.weight=weight;
}
Person.prototype.sayHi=function(){
console.log("hello");
};
function Student(name,age,sex,weight,score){
//借用构造函数
Person.call(this,name,age,sex,weight);
this.score=score;
}
var stu1=new Student("小明",20,"男","60kg",100);
console.log(stu1.name,stu1.age,stu1.sex,stu1.weight,stu1.score);
var stu2=new Student("小白",19,"女","50kg",130);
stu1.sayHi(); //报错 父级中的方法不能通过此方式继承
解决方案:继承的时候,不用改变原型的指向,直接调用父级的构造函数的方式来为属性赋值
借用构造函数:构造函数名字.call(当前对象,属性,属性...)
解决了属性继承,并且值不重复的问题
缺陷:父级类别中的方法不能继承
组合继承
组合继承:原型实现继承+借用构造函数继承
function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.sayHi=function(){
console.log("hi");
}
function Student(name,age,sex,score){
//借用了构造函数,解决了属性值重复问题
Person.call(this,name,age,sex)
this.score=score
}
//改变了原型指向,并在原型中添加了eat方法
Student.prototype=new Person();//不传值
Student.prototype.eat=function(){
console.log("eat");
}
var stu1=new Student("ss",20,"男",100);
console.log(stu1.name,stu1.age,stu1.sex,stu1.score);
stu1.sayHi();
stu1.eat();
var stu2=new Student("xx",25,"男",100);
console.log(stu2.name,stu2.age,stu2.sex,stu2.score);
stu2.sayHi();
stu2.eat();
//属性和方法都被继承了
拷贝继承
拷贝继承:把一个对象中的属性或者方法直接复制到另一个对象中
function Person(){}
Person.prototype.age=20;
Person.prototype.sex="男";
Person.prototype.height=180;
Person.prototype.play=function(){
console.log("play");
};
var obj2={};
for(var key in Person.prototype){
obj2[key]=Person.prototype[key];
}
console.log(obj2);
//Person的构造函数中有原型prototype,
//prototype是一个对象,把这个对象里的属性或者方法
//都循环遍历给了obj2