面向对象之创建对象模式和继承模式

目录

工厂函数模式

优点:

缺点:

构造函数模式

优点:

缺点:

原型对象模式

优点:

缺点:

组合模式        

 instanceof

 继承

继承分为三类,分别是:原型链继承、借用构造函数继承、组合继承(原型链继承+借用构造函数继承)

组合继承


从前面的学习可以知道创建单个对象有两种方法,一种是直接使用字面量 var obj = {},另一种则是使用构造函数 var obj = new Object() 来创建单个对象的。

那么,多个对象又如何创建呢?接下来,将介绍四种创建多个对象的方法。

工厂函数模式

// 工厂函数模式
function sayName(){
    console.log(this.name);
}
function person(name,age,gender){
    return{
        name:name,
        age:age,
        gender:gender,
        // 写在内部会造成方法冗余,每个子对象都会在堆区占据一块方法的区域
        // sayName:function(){
        //     console.log(this.ame);
        // }
        // 方法写在外部
        sayName:sayName
    }
}

var p1 = person('jemmy',21,'male');
var p2 = person('cammy',18,'female');
console.log(p1);
console.log(p2);
p1.sayName();
p2.sayName();

function dog(name,age){
    return{
        name:name,
        age:age
    }
}
var d1 = dog('闹闹',4);
console.log(d1);

 从输出结果可以看出该方法的优点和缺点:

优点:

可以批量创建对象        降低代码冗余

缺点:

无法区分对象的种类(全是object实例)        方法冗余(无法区分sayName是谁的方法)。

构造函数模式

// 构造函数
function sayName(){
    console.log(this.name);
}
function Person(name,age,gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = sayName;
}

var p1 = new Person('jemmy',21,'male');
var p2 = new Person('cammy',18,'female');
/**
 *  new关键字做了什么?
        1.创建一个实例对象 var p1 = new Person(){}
        2.将this指向实例对象    this -->p1
        3.执行函数体    p1.name = zhangsan;
        4.返回实例对象  return p1{}
 */
console.log(p1);
console.log(p2);
p1.sayName();
p2.sayName();

function Dog(name,age){
    this.name = name;
    this.age = age;
}
var d1 = new Dog('闹闹',4);
console.log(d1);

优点:

可以批量创建对象    可以区分种类

缺点:

方法冗余

原型对象模式

// 原型对象
function Person(){};
Person.prototype = {
    constructor:Person,
    name:'cammy',
    age:18,
    gender:'female',
    sayName:function(){
        console.log(this.name);
    }
}
var p1 = new Person();
var p2 = new Person();
console.log(p1,p2);
console.log(p1.name,p2.name);
Person.prototype.friends = [];
p1.friends.push('tom');
console.log(p1.friends);
console.log(p2.friends);

优点:

解决了方法冗余  批量创建对象

缺点:

所有的实例属性和方法都一样(如图中给p1对象数组中添加一个元素,结果p2也添加上了)

组合模式        

// 组合模式 构造函数 + 原型对象
//将实例私有属性和方法全部放在构造函数中
//将实例公共属性和方法都放在原型对象中
function Person(name,age,gender){
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.friends = [];
}
Person.prototype = {
    constructor:Person,
    sayName:function(){
        console.log(this.name);
    }
}

var p1 = new Person('jemmy',21,'male');
var p2 = new Person('cammy',18,'female');
console.log(p1,p2);
p1.friends.push('tom');
console.log(p1,p2);
p1.sayName();
p2.sayName();

 instanceof

判断当前实例对象是否处在原型链上

判断是否是某一个构造函数的实例对象

/**
 * instanceof 判断当前实例对象是否处在原型链上
 * 判断是否是某一个构造函数的实例对象
 */
console.log(p1 instanceof Person);
console.log(p2 instanceof Person);
console.log(p1 instanceof Object);
console.log(p2 instanceof Object);
console.log(Person instanceof Object);

 继承

继承分为三类,分别是:原型链继承、借用构造函数继承、组合继承(原型链继承+借用构造函数继承)

这里介绍组合继承

组合继承

// 构造创建函数 父函数
function Animal(type,age,weight){
    this.type = type;
    this.age = age;
    this.weight = weight;
}

// 公共方法
Animal.prototype = {
    constructor:Animal,
    sayType:function(){
        console.log(this.type);
    }
}

// 借用构造函数继承 
function Dog(type,age,weight,name){
    // Animal.call(this,type,age,weight);
    // Animal.apply(this,[type,age,weight]);
    Animal.bind(this)(type,age,weight);
    this.name = name;
}

// var d1 = new Dog('狗',3,'20kg','闹闹');
// console.log(d1);

// 原型链继承
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
Dog.prototype.sayName = function(){
    console.log(this.name);
}
// Dog.prototype.sayType = function(){
//     console.log('我是子构造函数的原型对象');
// }
var d1 = new Dog('狗',3,'20kg','闹闹');
console.log(d1);
d1.sayType();

借用构造函数继承的重点在于

// Animal.call(this,type,age,weight);
// Animal.apply(this,[type,age,weight]);
Animal.bind(this)(type,age,weight);

需要调用父构造函数并且将this指向修改为子构造函数实例,可以使用call,apply或bind来改变指向,其介绍详情见函数的基本知识_学前端的狗头苏丹的博客-CSDN博客

原型链继承的重点在于

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

通过第一句来将子构造函数的原型对象指向父构造函数的实例对象去调用父构造函数中的方法。

通过第二句来将子构造函数重新指向子构造函数。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学前端的狗头苏丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值