js构造函数和原型
构造函数是一种特殊的函数,主要用来初始化对象,因为对象成员变量赋初始值,它总与new一起使用,我们可以把对象中的一些个公用的属性和方法抽出来,然后封装到这个函数里面。
①new在执行中的步骤:
- 在内存中创建一个新的对象;
- 让this指向这个新的对象;
- 执行构造函数里的代码,给这个新的对象添加属性和方法(复制);
- 返回这个新对象(所以构造函数里面不需要return)
//1.使用 new object()来创建对象
var obj1= new object();
//2.利用对象字面量来创建对象
var obj2={};
//3.利用构造函数来创建对象;
function Star(uname,age){
this.uname=uname;
this.age=age;
this.sing=function(){
console.log('唱歌’);
}
}
var xnn=new Star('小楠楠‘,20);
//1.实例成员就是构造函数内部通过this添加的成员
uname age sing就是实例成员
//实例成员只能通过实例化的对象来访问
console.log(xnn);
xnn.sing();
xnn.log(Star.uname);//undifine不可以通过构造函数来访问实例
//2.添加静态对象,在构造函数本身上添加的成员sex
Star.sex='男’;
//静态成员只能通过构造函数来访问
console.log(Star.sex);
console.log(xnn.sex);//undifine不能通过对象来访问
其实就是把对象的公共部分放到构造函数里面去
构造函数的缺陷:浪费内存。每一个对象的函数都要开辟一个空间。
②解决方法:构造函数(原型)prototype(原型是一个对象)
构造函数通过原型分配的函数是所有对象所共享的,每一个函数都有prototype属性,指向另外一个对象,注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
function Star(uname,age){
this.uname=uname;
this.age=age;
}
Star.prototype.sing=function(){
comsole.log('唱歌‘);//把方法定义在prototype中
}
var xnn=new Star('小楠楠’,20);
xnn.sing();//xnn这个对象的实例可以直接享有sing的方法;
所以说,一般我们把公共的属性定义在构造函数里面,公共的方法我们放到原型对象身上。
这里的问题是我们把sing定义给了Star的原型对象身上,为什么我小楠
楠这个对象就可以使用这个方法呢,小楠楠也没有这个方法啊所以我们看下面
对象原型_proto_
每个对象都会有一个属性_proto_指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有_proto_原型的存在
function Star(uname,age){
this.uname=uname;
this.age=age;
}
Star.prototype.sing=function(){
comsole.log('唱歌‘);
}
var xnn=new Star('小楠楠’,20);
xnn.sing();对象身上系统自己添加了一个_proto_指向构造函数的原型对象prototype
console.log(xnn._proto_===Star.prototype);//true
//方法的查找规则,首先先查找xnn.对象上是否有sing方法,如果有就执行这个对象上的sing。
//如果没有sing这个方法,因为有_proto_的存在,就去构造函数原型对象prototype身上去查找sing这个方法
注意
- _proto_对象原型和原型对象prototype是等价的;
- _proto_对象原型的意义在于为对象查找机制提供一个方向,或者说一条线路,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
原型constructor构造函数
对象原形_proto_和构造函数prototype原型对象里面都有一个属性constructor属性,constructor我们称为构造函数,指回构造函数本身。
-
function Star(uname,age){ this.uname=uname; this.age=age; } Star.prototype.sing=function(){ console.log('唱歌‘); } var xnn=new Star('小楠楠’,20); xnn.sing(); console.log(xnn._proto_constructor);//此时返回的就是构造函数本身
很多情况下,我们需要手动的利用constructor这个属性指回原来的构造函数,就是当公共的方法有多个的时候
Star.prototype.sing=function(){
console.log('唱歌‘);
}
Star.prototype.movie=function(){
console.log('开始演‘);
}
把它们合并一下;
Star.function={
sing.function{
console.log('唱歌’);
}
movie.function{
console.log('开始表演‘);
}
这里对原型对象进行赋值操作之后,相当于新添加了对象,它并没有指回我们的构造函数,后面用了赋值把这个prototype全部都覆盖掉了,那prototype就没有这个constructor属性了
这时只需要在原型对象中添加回constructor就好了
Star.function={
constructor:Star,//给它添加回去,此时它又能指向原来的Star了
sing.function{
console.log('唱歌’);
}
movie.function{
console.log('开始表演‘);
}