1.之前我们学过的创建对象的方式为3种:对象字面量,new Object() 自定义构造函数
(1)利用Object来创建对象
// 1.利用Object创建对象
var obj1=new Object()
(2)利用对象字面量来创建对象
//利用对象字面量创建对象
var obj2={
name:'张三',
age:18
}
(3)利用构造函数来创建对象
//利用自定义构造函数创建对象
function Star(uname,usex){
this.uname=uname;
this.usex=usex;
this.sing=function(){
alert('会唱歌')
}
}
var ldh=new Star('刘德华','男')
console.log(ldh);
console.log(ldh.sing());
2.构造函数:是一种特殊的函数,主要是用来初始化对象,【为对象成员变量赋初始值】,它总与new一起使用,我们可以将一些公共的属性和方法抽取出来然后将其封装在构造函数中
在JS中,使用构造函数的注意事项
(1)构造函数用于创造某一类的对象,其首字母需要大写
(2)构造函数与new一起使用才有意义
3.new在执行时可以做的四件事情
(1)在内存中创造一个空对象
(2)让this指向这个对象
(3)执行构造函数里面的代码,给这个新对象添加属性和方法
(4)返回这个新的对象【所以构造函数里不需要加return】
2.实例成员和静态成员【构造函数中的属性和方法称为成员】
1.静态成员:在构造函数本身上添加的成员为静态成员,只能由构造函数本身来访问
// 静态成员
Star.age=19;
//访问
console.log(Star.age)
原来Star函数没有age这个属性,通过Star来添加,所以age就是静态成员 需要通过构造函数来访问
2.实例成员:在构造函数内部创建的对象成员【在构造函数内部通过this添加的成员】称为实例成员,只能有实例化对象来访问
通过代码理解:
构造函数代码
//利用自定义构造函数创建对象
function Star(uname,usex){
this.uname=uname;
this.usex=usex;
this.sing=function(){
alert('会唱歌')
}
}
//实例对象
var ldh=new Star('刘德华','男')
//因为uname usex sing都是实例成员 所以只能通过ldh来访问
console.log(ldh.uname);
console.log(ldh.usex);
ldh.sing();
在上述构造函数中,uname,usex,sing都是实例化成员并且只能通过实例对象访问
构造函数会出现浪费内存的问题:如果构造函数中有方法,那么我们每次创建一个新的实例对象构造函数都会开辟出一个新的内存空间来存储相同的方法,所以会出现浪费内存的方法
3.构造函数原型prototype
1.构造函数通过原型分配的函数是所有对象共享的
2、prototype:每一个构造函数都有一个prototype属性,指向另一个对象【prototype就是一个对象,这个对象的所有方法和属性都会被构造函数所拥有】
function Star(uname,usex){
this.uname=uname;
this.usex=usex;
}
Star.prototype.sing=function(){
console.log(this.uname+'会唱歌');
}
var ldh=new Star('刘德华','男')
var zyx=new Star('张艺兴','男')
ldh.sing();
zyx.sing();
3.对象原型:proto
对象都会有一个属性_proto_指向构造函数的prototype原型对象。
对象上的对象原型_proto_与构造函数上的prototype是等价的
方法查找规则:首先看实例对象身上是否由我们要调用的方法,如果有就去执行;如果没有,因为_proto_的存在,就去构造函数的原型对象prototype上去查找
4.constructor构造函数
1.对象原型和够凹函数原型对象里面都有一个constructor属性,constructor称为构造函数指回构造函数本身
2.作用:主要用于记录该对象引用哪个构造函数,他可以让原型对象重新指回原来的构造函数【手动指回原来的构造函数】
案例
<script>
function Star(uname,usex){
this.uname=uname;
this.usex=usex;
}
// 构造函数的原型对象,实例化对象的对象原型
Star.prototype={
sing:function(){console.log(this.uname+'会唱歌');},
movie:function(){console.log(this.uname+'有演技');}
}
var ldh=new Star('刘德华','男')
var zyx=new Star('张艺兴','男')
console.log(ldh.__proto__);
console.log(Star.prototype);
</script>
按照理论来说,两个输出都应该指向构造函数Star,但是控制台输出却不是,因为我们将Star.prototype进行了赋值,后面的对象将原来prototype里的对象进行了覆盖,所以最后不能之后构造函数,此时就需要我们手动的添加构造函数
<script>
function Star(uname,usex){
this.uname=uname;
this.usex=usex;
}
// 构造函数的原型对象,实例化对象的对象原型
Star.prototype={
// 手动添加指回构造函数
constructor:Star,
sing:function(){console.log(this.uname+'会唱歌');},
movie:function(){console.log(this.uname+'有演技');}
}
var ldh=new Star('刘德华','男')
var zyx=new Star('张艺兴','男')
console.log(ldh.__proto__);
console.log(Star.prototype);
</script>
控制台输出结果