通过构造函数Person产生的对象,产生的对象没有共用方法
缺点:产生一个对象,就会产生一个方法 ,增加了内存的开销;
//创建构造函数
function Person(name,age){
this.name=name;
this.age=age;
this.show=function(){
console.log("我叫"+this.name+"我今年"+this.age+"岁")
}
}
var xiaoming=new Person("小明","18");
var xiaohong=new Person("小红","19");
console.log(xiaoming,xiaohong);
console.log(xiaohong.show===xiaoming.show);//false
解决办法:让对象共用一个方法
因为函数是应用类型,所以将函数提炼到构造函数外部
//创建构造函数
function Person(name,age){
this.name=name;
this.age=age;
this.show=show;
}
//将函数提炼到构造函数外部
function show(){
console.log("我叫"+this.name+"我今年"+this.age+"岁")
}
var xiaoming=new Person("小明","18");
var xiaohong=new Person("小红","19");
console.log(xiaoming,xiaohong);
console.log(xiaohong.show===xiaoming.show);//true
新的问题出现:出现了一个全新变量
解决问题:消灭这个全新变量
解决办法:将obj设置为Person的属性
// Person
function Person(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
alert(this.name)
}
}
// Person.obj={
// show:function (){
// console.log("我叫"+this.name+"我今年"+this.age+"岁")
// },
// say:function (){
// console.log("this is say")
// }
// }
// 在原型书写
Person.prototype.show=function (){
console.log("我叫"+this.name+"我今年"+this.age+"岁")
}
Person.prototype.say=function (){
console.log("this is say")
}
var xiaoming=new Person("小明","18");
var xiaohong=new Person("小红","19");
console.log(xiaoming,xiaohong);
console.log(xiaohong.show===xiaoming.show);//true
原型对象
prototype 和** proto和constructor**
通过构造函数访问原型对象: prototype
通过产生的实例访问原型对象: _proto _
通过原型对象访问构造函数:constructor
原型链
xiaoming这个对象并没有show方法,但却可以调用show方法,属性和方法查找过程为:
1、查找当前对象是否拥有该属性或方法,如果有则直接使用
2、如果没有则去当前对象的原型对象中去查找,如果则使用
3、如果当期对象的原型对象中没有,则去当前对象的原型对象的原型对象去查找,直到最顶级对象
如果有则使用,如果没有属性则为undefined,方法则报错 typeError
综上所述,对象—》原型对象—》原型对象—》…—》最顶级对象,这样就形成了一个链式查找的过程,将这个链称之为原型链 Object.prototype 顶级对象
关键字
- "attr" in obj (检测是否可以通过该对象访问这个属性,值为布尔类型)(true 可以 false 不可以)
in 就是检测一个对象及其原型链中是否存在该属性 - :obj.hasOwnProperty(“attr”) **(检测对象是否有property这个属性)
// Person
function Person(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
alert(this.name)
}
}
var xiaoming=new Person("小明","18");
//"attr" in obj 检测是否可以通过该对象访问这个属性
console.log("happy" in xiaoming);//false
console.log("name" in xiaoming );//true
//obj.hasOwnProperty("property") 检测对象是否有property这个属性
console.log(xiaoming.hasOwnProperty("happy"));//false
console.log(xiaoming.hasOwnProperty("age"));//true
安全类 (无论是new还是函数直接调用都产生对象)*
/*
无论是new还是函数直接调用都产生对象
问题:当调用函数的时候产生和new操作一样的对象
1、判断函数不是new的操作
2、 return new 函数
*/
function Student(name, sex) {
if (!(this instanceof Student)) {
return new Student(name, sex);
}
this.name = name;
this.sex = sex;
}
var s1 = new Student('xiaoming', 'nan');
var s2 = Student('lili', 'nv');
console.log(s1, s2);
继承
类式继承:
问题 : 继承了原型对象中很多无用的属性和方法
// Person
function Person(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
alert(this.name)
}
}
function Student(name,age,sex,grade){
this.name = name;
this.age = age;
this.sex= sex;
this.grade = grade;
}
//类式继承 子类构造函数的原型指向父类的实例
Student.prototype=new Person();
//子类构造函数的原型的constructor指向子类 (完成了原型链的修改)
Student.prototype.constructor=Student;
//给子类添加方法必须在继承之后
Student.prototype.say=function(){
console.log(222)
}
var xiaoming=new Student("小明",18,"男",88)
console.log(xiaoming);//子类构造函数的原型就指向了父类的实例
构造函数式继承(不是真的继承,只是简化了重复赋值的问题)
//构造函数式的继承
function Student(name,age,sex,grade){
Person.apply(this,arguments)
this.grade=grade;
}
Student.prototype.say=function(){
console.log(222)
}
var xiaoming=new Student("小明",18,"男",88)
xiaoming.sayHello();
console.log(xiaoming);//只是简化了重复赋值的问题,子类构造函数的原型指向没有改变
组合继承(类式继承和构造函数继承的结合)
问题 : 继承了原型对象中很多无用的属性和方法
function Person(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
alert(this.name)
}
}
//组合继承 (类式继承和构造函数继承的结合)
function Student(name,age,sex,grade){
//构造函数继承(解决重复赋值的问题)
Person.apply(this,arguments)
this.grade = grade;
}
//类式继承 (继承原型上的方法)
Student.prototype=new Person()
Student.prototype.constructor=Student;
Student.prototype.Hello=function(){
console.log("hello");
}
var xiaoming=new Student("小明",18,"男",88)
console.log(xiaoming);
寄生式继承:
//构造函数
function Person(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
alert(this.name)
}
}
function Student(name, sex, age, grade) {
this.name = name;
this.age = age;
this.sex= sex;
this.grade = grade;
}
Person.prototype.show=function(){
console.log("show")
}
//寄生类继承
function Fun(Parent,Son){
//创建一个空的构造函数(寄生类)
var F=function(){
};
//让寄生类的原型指向父类的原型
F.prototype=Parent.prototype;
//让子类的原型指向寄生类的实例
Son.prototype=new F();
//设置constructor
Son.prototype.constructor=Son;
}
Fun(Person,Student);
var xiaoming=new Student("小明",18,"男",88)
console.log(xiaoming);
xiaoming.show();//show
寄生组合式继承()
//构造函数
function Person(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
alert(this.name)
}
}
Person.prototype.show=function(){
console.log("show")
}
function Student(name,age,sex,grade){
//构造函数继承(解决重复赋值的问题)
Person.apply(this,arguments)
this.grade = grade;
}
//寄生类继承
function Fun(Parent,Son){
//创建一个空的构造函数(寄生类)
var F=function(){
};
//让寄生类的原型指向父类的原型
F.prototype=Parent.prototype;
//让子类的原型指向寄生类的实例
Son.prototype=new F();
//设置constructor
Son.prototype.constructor=Son;
}
Fun(Person,Student);
var xiaoming=new Student("小明",18,"男",88)
console.log(xiaoming);
xiaoming.show();//show