function Star(name,age){
this.name=name;
this.age=age;
this.sing=function(){
console.log("我会唱歌")
}
}
var ldh=new Star('刘德华',18);
//实例成员就是构造函数内部通过this添加的成员 name age sing就是成员
// 实例成员就是实例化的对象来访问
console.log(Idh.name);
Idh.sing()
console.log(Idh.name); //实例成员只能通过实例化的对象来访问
console.log(Star.name); //不可以通过构造函数来访问实例成员
//静态成员 在构造函数本身上添加的成员 sex就是静态成员
Star.sex="男 ";
//静态成员只能通过构造函数来访问
console.log(Star.sex);
console.log(Idh.sex); //不能通过对象来访问静态成员
//原型对象
es6之前是 面向对象之前是由构造函数实现的,缺点是把方法放在构造函数里面,当我们创建实例的时候,会单独再创建一个内存空间,存放函数
我们在创建构造函数的两个不同实例对象的时候,会开辟两个不同的内存空间,比较浪费空间
// 对象使用同一个函数,比较节省内存
// 构造函数通过原型分配的函数时所有对象所共享的
// 每一个构造函数都有一个prototype属性,指向另一个对象。注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
// 我们可以把那些不变的方法,直接定义在prototype对象上,这样所有的对象的实例可以共享这些方法
// 原型是一个对象,我们也称为prototype为原型对象
// 原型的作用是共享方法
function Star(name,age){
this.name=name;
this.age=age;
// this.sing=function(){
// console.log("我会唱歌")
// }
}
//一般情况下,我们的公共属性定义到构造函数里面,公共的属性和方法放到原型对象身上
Star.prototype.sing=function(){
console.log('我会唱歌');
}
var ldh=new Star( '刘德华',18);
var zxy=new Star('张学友',18);
console.log(ldh)
console.log(zxy);
// Idh.sing()
// zxy.sing()
//console.log(Idh.sing===zxy.sing); //false 比较是地址
//共享方法后:console.log(Idh.sing===zxy.sing) //true
// 对象原型_proto_
// 对象都会有一个属性_proto_指向构造函数的prototype原型对象
// 之所以对象可以使用构造函数prototype的属性和方法,就是因为对象有_proto_原型的存在
// __proto__对象原型和原型对象prototype是等价的
function Star(name,age){
this.name=name;
this.age=age;
// this.sing=function(){
// console.log("我会唱歌")
// }
}
Star.prototype.sing=function(){
console.log('我会唱歌');
}
var ldh=new Star( '刘德华',18);
var zxy=new Star('张学友',18);
console.log(ldh); //对象身上系统自动添加一个__proto__指向我们的构造函数的原型对象prototype
console.log(Lidh.__proto__===Star.prototype); //true
// 方法的查找规则:首先先看ldh对象身上是否有sing方法,如果有就执行这个对象
// 如果没有sing这个方法,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找sing这个方法
成员的查找机制
function Star(name,age){
this.name=name;
this.age=age;
// this.sing=function(){
// console.log("我会唱歌")
// }
}
Star.prototype.sing=function(){
console.log('我会唱歌');
}
Star.prototype.sex='女'
// Object.prototype.sex='男'
ldh.sex='男' //如果实例对象也有,原型对象上也有,就用实例对象上的(就近原则)
var ldh=new Star( '刘德华',18);
console.log(ldh.sex);
原型对象this的指向
function Star(name,age){
this.name=name;
this.age=age;
// this.sing=function(){
// console.log("我会唱歌")
// }
}
var that;
Star.prototype.sing=function(){
console.log('我会唱歌');
that=this;
}
var ldh=new Star( '刘德华',18);
//在构造函数中,里面this指向的是对象实例ldh
ldh.sing()
console.log(that===ldh); //true
// 2.原型对象函数里面的this指向的是实例对象ldh
//原型对象的应用,扩展内置对象方法
console.log(Array.prototype);
Array.prototype.sum=function(){
var sum=0;
for(var i=0;i sum+=this[i] } return sum; } // Array.prototype={ // sum:function(){ // var sum=0; // for(var i=0;i // sum+=this[i] // } // return sum; // } // } var arr=[1,2,3]; console.log(arr.sum()); // 6 arry是实例对象它调用了原型对象的sum方法 //借用父构造函数继承属性 // 1.父构造函数 function Father(name,age){ // this指向父构造函数的对象实例 this.name=name this.age=age } // 2.子构造函数 function Son(name,age,sex){ // this指向子构造函数的对象实例 Father.call(this,name,age) //首先调用父构造函数,把夫构造函数的this改成子构造函数的this this.sex=sex } var son=new Son('刘德华',18,'男'); console.log(son); //刘德华 18 男 原型对象继承方法 function Father(name,age){ // this指向父构造函数的对象实例 this.name=name this.age=age } // 父构造函数专门的方法 Father.prototype.money=function(){ console.log(10000); } // 2.子构造函数 function Son(name,age,sex){ // this指向子构造函数的对象实例 Father.call(this,name,age) //首先调用父构造函数,把父构造函数的this改成子构造函数的this this.sex=sex } // 这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会发生改变 // Son.prototype=Father.prototype; 最终方法 Son.prototype=new.Father();//子的原型对象等于父的实例 //Son 继承了父的构造方法的同时,它自已的constructor也发生了改变, 所以如果利用对象的形式修改了原型对象,别忘了利用constructo指回原来的构造函数 Son.prototype.constructor=Son; // 这个是子构造函数专门的方法 Son.prototype.exam=function(){ console.log('孩子要考试'); } var son=new Son('刘德华',18,'男'); console.log(son);