js之设计模式(工厂模式、构造器模式、原型模式、组合模式)

一、工厂模式

作用: 创建对象;降低代码冗余度。
优点: 批量创建对象 封装创建对象的函数 提高代码复用率
缺点: 无法区分创建出来的对象种类 方法冗余
将创建对象的代码封装在一个函数中

var getName=function(){
	console.log(this.name);
};
function Person(name,age,gender){
	    return {
	        name:name,
	        age:age,
	        gender:gender,
	        getName:getName
	    }
	}
	
	var p1=Person('terry',12,'男');
	var p2=Person('larry',13,'男');
	console.log(p1.getName===p2.getName);//false
	console.log(p1 instanceof Object);//true

二、构造函数模式

优点: 可以区分种类
缺点: 方法还是冗余
构造函数本身也是函数,只是以函数的形式为自己的对象类型定义属性和方法。

	var getName=function(){
	    console.log(this.name);
	}
	function Person(name,age,gender){
	    this.name=name;
	    this.age=age;
	    this.gender=gender;
	    this.getName=getName;
	}
	var p1=new Person('terry',12,'男');
	var p2=new Person('larry',13,'男');
	console.log(p1,p2);
	console.log(p1.getName===p2.getName);//true

构造函数模式与工厂模式的区别?

  • 共同点: 都是函数,都可以创建对象,都可以传入参数
  • 不同点:
    • 工厂模式:

      1. 函数名是小写
      2. 有返回值
      3. 直接调用函数就可以创建对象
    • 自定义构造函数:

      1. 函数名是大写(首字母)
      2. 没有return返回值
      3. this是当前的对象,属性和方法直接赋值给了 this。
      4. 通过new的方式来创建对象
      5. 没有显示地创建对象

拓展:
构造函数本身也是函数,如果用new 的方式创建一个实例对象

function Person(name, age, gender) {
  this.name = name;
  this.age = age;
  this.gender = gender;
}


var person1 = new Person("zhangsan", 29, "male");

console.log(person1 instanceof Object)//true
console.log(person1 instanceof Person)//true
console.log(person1 instanceof Function)//true
console.log(Person instanceof Object)//true
console.log(Person instanceof Function)//true

此时自定义的构造函数Person的原型链为:
在这里插入图片描述
Person创建出来的实例对象的原型链为:
在这里插入图片描述

三、原型模式

所有的属性和方法都放到原型对象中,不单独使用
缺点: 它弱化了向构造函数传递初始化参数的能力,会导致所有实例默认都取得相同的属性值
注意: 尽管可以这么做,但并不推荐在产品环境中修改原生对象原型。这样做很可能造成误会,而且可能引发命名冲突。另外还有可能意外重写原生的方法。

	function Person() {};
	Person.prototype = {
	    constructor: Person,
	    name: 'zs',
	    age: 12,
	    firends: [],
	    getName: function() {
	        console.log(this.name);
	    }
	}
	var p1 = new Person();
	var p2 = new Person();
	console.log(p1.getName === p2.getName); //true
	p1.firends.push('ls');
	console.log(p1.firends, p2.firends); //[ 'ls' ] [ 'ls' ]

只要给对象实例添加一个属性,这个属性就会遮蔽原型对象上的同名属性,也就是虽然不会修改它,但会屏蔽对它的访问。

function Person() { }
Person.prototype={
	name:"zs",
	age: 29,
	sayName:function () {
 	 console.log(this.name);
	};
}
var p1 = new Person();
var p2 = new Person();

// 通过hasOwnProperty()可以查看访问的是实例属性还是原型属性
console.log(p1.hasOwnProperty('name')); //false

p1.name = "lisi";
console.log(p1.name); // lisi,来自实例
//只在重写 p1 上 name 属性的情况下才返回 true,表明此时 name 是一个实例属性,不是原型属性
console.log(person1.hasOwnProperty('name')); //true

console.log(p2.name); // zhangsan,来自原型

console.log(p2.hasOwnProperty('name'));//false

delete p1.name;
console.log(p1.name); // zhangsan,来自原型

四、组合模式(构造函数模式加原型模式)

构造函数中放实例私有的属性,构造函数原型对象中放共有属性和方法

	// 在构造函数中 定义一些不需要共享的属性
	function Person(name, age, friends) {
	  this.name = name,
	  this.age = age,
	  this.friends = friends
	}
	// 将要共享的参数或方法定义在原型上
	Person.prototype = {
	  sayName(){
	    console.log(this.name);
	  }
	}
	// 改变构造函数的指向
	Object.defineProperty(Person.prototype,'constructor',{
	  enumerable: false,
	  value: Person
	})
	var p1 = new Person('zs', 38, ['ls','ww'])
	var p2 = new Person('ls', 40)
	console.log(p1.sayName === p2.sayName);//true

这种模式是目前在ECMAScript中使用最广泛,认同度最高的一种创建自定义类型的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值