创建对象的多种模型

本文详细介绍了JavaScript中创建对象的几种模式,包括工厂模式、自定义构造函数模型和原型模型。针对每种模式的优缺点进行了分析,如工厂模式适合批量创建对象但无法分类,构造函数解决了分类问题但方法会被重复创建。最终提出了组合模式,通过结合构造函数和原型模式,实现方法共享和避免实例间的属性共享,以优化内存使用和提高代码效率。
摘要由CSDN通过智能技术生成

1、工厂模式

        首先来看看常用的两种创建对象的方式:

                1、字面量创建

                        

var person = {
    name:'zhansgan',
    age:18,
    sayName:function() {
        console.log(this.name);
    }
}

                   2、构造函数

// 构造函数
var person = new Object()
person.name = 'zhansgan'
person.age = 13
person.sayName = function() {
    console.log(this.name);
}

              3、工厂模模式创建

// 将创建对象的代码封装在一个函数中
function createPerson(name,age,gender) {
    var person = new Object()
    person.name = name;
    person.age = age;
    person.gender = gender;
    person.sayName = function () {
        console.log(this.name);
    }
    return person;
}
// 利用工厂函数来创建对象
var person1 = createPerson('zhangsan',18,'male')
var person2 = createPerson('lisi',16,'female')
console.log(person1 instanceof createPerson);//false

工厂模型优点是:可以批量的创建对象,只要往函数里面传递不同的参数就能创建出不同的实例

工厂模式缺点是:无法进行分类,创建的实例指向的原型都是Object,就相当于你创建一个人使用的Object,创建的狗也是使用Object。且实例调用的方法不是同一个方法,也就是说每次创建一个实例,同时也会创建出实例里面的方法,造成内存空间的浪费和代码冗余。

2、自定义构造函数模型

        自定义构造的出现是为了解决无法分类的问题。

        使用自定义的构造函数可以定义出不同的种类。

function Person(name,age,gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = function () {
        console.log(this.name);
    }
}
// 创建 p1、p2实例
var p1 = new Person('zhangsan',15,'male')
var p2 = new Person('lisi',19,'female')
p2.sayName()
p1.sayName()

要创建Person的实例,应该使用new操作符。new在js中做了以下的事情:

        1、创建了一个实例对象 Person

        2、this指向Person实例对象 this---p1,p2

        3、执行函数

        4、返回Person实例对象

 

构造函数与普通函数唯一的区别就是调用方式不同。

但是仍然存在每次创建一个对象实例,其定义的方法也会在每个实例上再创建一次!!!

还是存在内存空间的浪费!!

解决方法:把在构造函数内部定义的方法移到函数外部去,也就是将方法定义在全局作用域中

var Person = function (name , age , gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.sayName = sayName;
}
function sayName() {
    console.log(this.name);
}

这样解决了创建实例就创建方法的问题

但是,新的问题又出现了

在构造函数外部定义方法,该方法就是处于全局作用域中

随着方法的不断增多,会扰乱全局作用域,而且放在全局作用域中其他的实例也能调用!!

但是我并不想给其他对象调用!!

3、原型模型

        解决方法:将方法定义到原型模式上,对象可以调用原型模式上的方法

function Person(params) {}
Person.prototype.name = 'zhangsan'
Person.prototype.age = 18
Person.prototype.gender = 'male'
Person.prototype.sayName = function () {
    console.log(this.name);
}
var person1 = new Person()
person1.sayName()
var person2 = new Person()
person2.sayName()
// 验证实例1和实例2所调用的方法是否是同一个
console.log(person1.sayName === person2.sayName);

这样就解决了方法放在全局作用域的问题了,但是原型上的所有属性和方法是在实例之间都是共享的,但是总有一些方法,是我们不想共享的,那么怎么办??

4、组合模式

解决方法:使用构造函数和原型模式的组合模式

构造函数的问题:方法不能共享

原型模型的问题:全部方法共享

那么我们就把想要共享的方法放在原型模型中,不想共享的方法放在构造函数中不就行了!!

//构造函数创建
function Person(name, age, gender) {
  this.name = name;
  this.age = age;
  this.gender = gender;
  this.firends = ['zhangsan', 'lisi'];
}
//原型创建
Person.prototype = {
  //constructor: Person,
  sayName: function () {
    console.log(this.name);
  }
};
  //改变构造函数的指向
Object.defineProperty(Person.prototype,'constructor',{
    enumerable:fasle
    value:Person
    })
var p1 = new Person('larry', 44, 'male');
var p2 = new Person('terry', 39, 'male');

p1.firends.push('robin');
console.log(p1.firends); // [ 'zhangsan', 'lisi', 'robin' ]
console.log(p2.firends); // [ 'zhangsan', 'lisi' ]
console.log(p1.firends === p2.firends); // false
console.log(p1.sayName === p2.sayName); // true

 千万别忘记对象的指向的问题!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值