JavaScript 工厂函数模式&构造函数模式

1.JavaScript工厂模式

工厂模式的主要作用是用来创建对象的,降低代码冗余度

应用场景:当你想要批量生产同种类的对象的时候;比如,你想生成一个班级的40个学生,每个学生都有姓名、年龄等特征。这时候你创建一个“工厂”,把信息丢到工厂里,工厂就给你造一个人出来,非常方便。

创建对象的方式有:

  • 字面量方式创建对象
// 字面量创建对象
var obj1={
    name:'zhangsan',
    age:18
}
  • new Object()创建对象
// new Object()创建对象
var obj2=new Object();
  • 工厂模式创建对象
// 使用工厂模式创建对象
// 1.创建一个函数  工厂函数
function createPerson(name,age,gender){
    // 2.使用构造函数创建一个模板实例
    var person=new Object();
    // 3.给模板实例赋值
    person.name=name;
    person.age=age;
    person.gender=gender;
    person.sayName=function(){
        console.log(this.name);
    }
    // 4.返回一个实例对象
    return person;
}
// 使用工厂函数创建实例
var p1=createPerson('zhangsan',18,'male')
var p2=createPerson('lisi',19,'female')
console.log(p1);
console.log(p2);
p1.sayName()
p2.sayName()

工厂模式的优缺点

​ **优点:**只要我们往工厂函数里面塞参数,工厂函数就会像生产产品一样早个人出来

​ **缺点:**这种方式的本质上是将创建对象的过程进行了封装,本质并没有改变,我们创建一个student时无法知道其具体的数据类型,只知道这是一个对象,往往实际开发中我们需要确定这个对象到底时个Person的实例还是Dog的实例

这时可以使用自定义构造函数模式

2.构造函数模式

ECMAScript的构造函数是能够创建对象的函数

2.1自定义构造函数

// 创建一个自定义的构造函数
// 1.使用函数来创建一个自定义的构造函数    function  函数表达式
function Person(name,age,gender) {
    // 2.直接使用this来进行一个赋值
    this.name =name;
    this.age=age;
    this.gender=gender;
    this.sayName=function(){
        console.log(this.name);
    }
    
}
// 3.使用new操作符  创建一个实例
var p1 =new Person('zhangsan',18,'male')
var p2 =new Person('lisi',19,'female')

person1.sayName(); // zhangsan
person2.sayName(); // lisi

这里的Person()与上面的工厂函数中的createPerson()内部的代码基本是一样的,只是有如下区别:

  • 没有显式地创建对象

  • 属性和方法直接赋值给了this

  • 没有return

    注意 :ECMAScript中区分构造函数与普通函数是:构造函数名称是以大写字母开头的,普通函数名称是以小写字母开头的

2.2创建Person实例

创建Person的实例,应使用new操作符

var p1 =new Person('zhangsan',18,'male')
var p2 =new Person('lisi',19,'female')

(1)在内存中创建一个新对象

(2)这个新对象内部的[[Prototype]]特性被赋值为构造函数的Prototype属性

(3)构造函数内部的this被赋值为这个新对象(即this指向新对象)

(4)执行构造函数内部的代码块(给新对象添加属性)

(5)如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象

以上的p1,p2分别保存着Person的不同实例。所有的对象都会从它的原型上继承一个constructor属性,对象的constructor属性指向Person

console.log(p1.constructor === Person); // true 
console.log(p1.constructor === Object); // false 
console.log(p2.constructor === Person); // true

2.3instanceof

constructor属性是用来标识对象类型的,只不过instanceof操作符能更可靠的确定对象的类型

instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原链上,也可以说是判断一个对象是不是某个对象的实例

console.log(p1 instanceof Object);//true
console.log(p1 instanceof Person);//true

所有自定义对象都继承自Object 。与工厂模式相对比,定义自定义构造函数可以确保实例被标识为特定类型,工厂模式不行

2.4 使用函数表达式自定义构造函数

构造函数可以赋值给一个变量的函数表达式来表示

// 创建一个自定义的构造函数
// 1.赋值给一个变量来创建一个自定义的构造函数    function  函数表达式
var Person=function (name,age,gender) {
    // 2.直接使用this来进行一个赋值
    this.name =name;
    this.age=age;
    this.gender=gender;
    this.sayName=function(){
        console.log(this.name);
    }
    
}
// 3.使用new操作符  创建一个实例
var p1 =new Person('zhangsan',18,'male')
var p2 =new Person('lisi',19,'female')

person1.sayName(); // zhangsan
person2.sayName(); // lisi

补充 在实例化时,如果不想传参数,那么构造函数后面的括号可加可不加。只要有new操作符,就可以调用相应的构造函数

2.5构造函数也是函数

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

​ 任何函数只要使用new操作符调用的就是构造函数,不使用new操作符调用的函数就是普通函数

function Person(name,age,gender) {
    
    this.name =name;
    this.age=age;
    this.gender=gender;
    this.sayName=function(){
        console.log(this.name);
    }
    
}
// 当作一个构造函数来使用
var p1 =new Person();
// 当作一个普通函数来使用
Person('lisi',19,'female');//添加到全局变量  浏览器 => window ; node => global
// console.log(global);
global.sayName();
var p2 =new Person();
// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "wangwu", 25, "male");
o.sayName(); // wangwu

这个案例展示了典型的构造函数调用方式,即使用 new 操作符创建一个新对象。然后是普通函数的调用方式。

​ 这时候没有使用 new 操作符调用 Person(),结果会将属性和方法添加到全局对象。这里要记住,在调用一个函数而没有明确设置 this 值的情况下(即没有作为对象的方法调用,或者没有使用call()/apply()调用),this 始终指向 Global 对象(在浏览器中就是 window 对象)。因此在上面的调用之后,Global 对象上就有了一个 sayName()方法,调用它会返回"lisi"。

​ 最后的调用方式是通过 call()(或 apply())调用函数,同时将特定对象指定为作用域。这里的调用将对象 o 指定为 Person()内部的 this 值,因此执行完函数代码后,所有属性和 sayName()方法都会添加到对象 o 上面。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值