设计模式及补充知识

补充

1、Object.prototype中的hasOwnProperty、isPrototypeof
hasOwnProperty //判断一个属性是否是实例自身的属性(不能是原型链上的属性)
isPrototypeof // 判断一个某一个原型对象是否在某个实例的原型链上,类似于instanceof

function Foo(){
	this.name = "haha";
}
			
Foo.prototype.age = 20;
			
var foo = new Foo();

//判断某一个属性是否是实例本身的属性
console.log(foo.hasOwnProperty("name"),foo.hasOwnProperty("age"));
//true false
		
//判断某一个原型对象是否在某个实例的原型链上
console.log(Foo.prototype.isPrototypeOf(foo),Object.prototype.isPrototypeOf(foo));

2、Object.assign
// 将一个或多个对象的可枚举(即可遍历到)的属性复制到第一个参数上,返回复制之后的结果。(注:如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。)

var arr = {a:1};
var arr1 = {b:2,c:3};
var arr2 = {d:4,e:5};
			
var result = Object.assign({},arr,arr1,arr2);
console.log(result);
// 打印arr arr1 arr2拼接到空对象{}的结果
// {a: 1, b: 2, c: 3, d: 4, e: 5}

3、Object.defineProperty
给对象添加某个属性,默认只设置值的情况下

var obj = {};
Object.defineProperty(obj,"a",{
	value:10
});
console.log(obj); // {a:10}
			
obj.a = 20;
console.log(obj.a); // 10,默认不可更改
			
for(let i in obj){
	console.log(i);  // 默认不可遍历到,无打印
}
			
delete obj.a;
console.log(obj.a); // 10,默认不可删除

进行设置权限操作

var obj = {};
Object.defineProperty(obj,"a",{
	value:10,
	writable:true,    // 可写
	enumerable:true,  // 可被遍历
	configurable:true // 可被删除
});
			
obj.a = 20;
console.log(obj.a); // 20  可被更改
			
for(let i in obj){
	console.log(i); // a 可被遍历到
}
			
delete obj.a;
console.log(obj.a); // undefined a属性已经被删除

深拷贝和浅拷贝

深拷贝:对于引用类型的数据,拷贝值而不是地址。(即拷贝之后,二者的操作互不影响)
浅拷贝:对于引用类型的数据,直接令相等,拷贝的是地址。(其中任意一个操作,都会影响另一个,因为他们指向的是同一块地址空间)
1、递归的方式实现深拷贝。

function deepCopy(obj){
	if(Array.isArray(obj)){
		//是数组
		var newObj = [];
	}else{
		//是对象
		var newObj = {};
	}
	//遍历
	for(var i in obj){
		if(typeof obj[i] == "object"){
			//是引用数据类型,则递归调用deepCopy()
			newObj[i] = deepCopy(obj[i])
		}else{
			//不是引用数据类型,则是简单数据类型,直接赋值
			newObj[i] = obj[i];
		}
					
	}
	//处理之后的复制对象数据返回
	return newObj;
}
var obj1 = {a:[1],b:2};
var newObj = deepCopy(obj1);
newObj.a.push(2);
console.log(newObj,obj1);
//{a:Array(2),b:2}  {a:Array(1),b:2}
//此种方法,无论是多少层,都能实现深拷贝

2、简单方式实现深拷贝,先转为JSON格式的字符串,再把JSON格式的字符串转为JSON类型的数据。

var obj1 = {a:[1,[11]],b:2};
var obj = JSON.parse(JSON.stringify(obj1));
console.log(obj);

设计模式

1、单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。

var singleTon = (function(){
	//定义一个_instance属性,保证只能有一个实例
	var _instance = null;
				
	function Foo(){
		this.prop = "";
	}
				
	Foo.prototype.fn = function(){};
	//返回对象,存放getInstance方法,只有被调用该方法时,才会执行new
	return {
		getInstance:function(){
			if(!_instance){
				_instance = new Foo();
			}
			//如果有实例存在,直接返回,没有实例,创建一个之后返回创建的实例
			return _instance;
		}
	}
})();
//匿名函数自调用,直接执行
						
console.log(singleTon.getInstance()==singleTon.getInstance());
// true

2、观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

var observer = {
	on:function(eventName,callback){
		//定义一个obj对象,存放事件处理函数的对象
		if(this.obj===undefined){
			this.obj = {};
		}
		//某个事件可能有多个事件处理函数,故每个事件的属性值为数组格式
		if(this.obj[eventName]===undefined){
			this.obj[eventName] = [callback];
		}else{
			this.obj[eventName].push(callback);
		}
	},
	emit:function(eventName){
		//如果该事件在事件处理函数对象中存在
		if(this.obj[eventName]){
			//遍历该事件的属性值(数组格式)
			for(var i = 0; i < this.obj[eventName].length; i++){
				//调用执行事件处理函数
				this.obj[eventName][i]();
			}
		}
	},
	remove:function(eventName,callback){
		//如果该事件在事件处理函数对象中存在
		if(this.obj[eventName]){
			//遍历
			for(var i = 0; i < this.obj[eventName].length; i++){
				//找到要移除的那个事件处理函数,进行移除
				if(this.obj[eventName][i]==callback){
					this.obj[eventName].splice(i,1);
				}
			}
		}
	}			
}
		
//个人中心模块注册了loginSuccess事件
observer.on("loginSuccess",function(){
	console.log("个人中心模块发生了改变");
})
//购物车
observer.on("loginSuccess",function(){
	console.log("购物车模块发生了改变");
})
//评论
observer.on("loginSuccess",foo)
		
function foo(){
	console.log("评论模块发生了改变");
}
observer.remove("loginSuccess",foo)
// 移除掉评论模块
				
observer.emit("loginSuccess");
//个人中心模块发生了改变
//购物车模块发生了改变

3、适配器模式:将一个类(对象)的接口(方法或者属性)转化成另外一个接口以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决。
(1)参数适配

function foo(a,b,c,d){
	console.log(a,b,c,d);
}
			
var params = {
	a:1,
	b:2,
	c:3,
	d:4
}
			
//适配器
var _adapter = function(obj){
	foo(obj.a,obj.b,obj.c,obj.d);
}
			
_adapter(params);
//能够通过参数适配器,实现不同格式的参数传递

(2)默认参数和传进来的参数适配

//opts 自定义参数  defaults默认
function foo(opts){
	var defaults = {
		a:1,
		b:2,
		c:3,
		d:4
	}
	var _adapter = {};
	//实现如果有默认参数值,使用默认参数值
	//否则使用传进来的参数值
	for(var i in defaults){
		_adapter[i] = opts[i] || defaults[i];
	}
	//_adapter为结合了默认参数和传进来参数的对象
	console.log(_adapter);
}
			
foo({a:10});
//{a: 10, b: 2, c: 3, d: 4}

(3)类的接口适配

var baiduMap = {
	show:function(){
		console.log("baidu");	
	}
};
			
var googleMap = {
	display:function(){
		console.log("google");
	}
};

//定义一个适配器
var _googleMapAdapter = {
	show:function(){
		baiduMap.show();
		googleMap.display();
	}
}
_googleMapAdapter.show();
//baidu
//google

(4)数据适配

var data = [{week:1,pv:100},{week:2,pv:200},{week:3,pv:300}];	
//要把week和pv分离处理成 [1,2,3]  [100,200,300]这种格式
			
var _weekAdapter = data.map(function(item){
	return item.week;
});
var _pvAdapter = data.map(item=>item.pv);
			
console.log(_weekAdapter);
//[1, 2, 3]
console.log(_pvAdapter);
//[100, 200, 300]

4、组合模式又称部分-整体模式,将对象组合成树形结构以表示“部分整体”的层次结构。

//酒店订单
function Hotel(){
			
}
Hotel.prototype.create = function(){
	console.log("创建了酒店订单");
}
		
//机票订单
function Ticket(){
			
}
Ticket.prototype.create = function(){
	console.log("创建了机票订单");
}
		
function Order(){
	this.orders = [];
}
Order.prototype.add = function(order){
	this.orders.push(order);
	return this;
}
Order.prototype.create = function(){
	for(var i = 0; i < this.orders.length; i++){
		this.orders[i].create();
	}
}
		
//两个机票订单  一个酒店订单
var order = new Order();
order
.add(new Ticket())
.add(new Ticket())
.add(new Hotel())
.create();
//2次打印  创建了机票订单
//创建了酒店订单

经典面试题

var Event = {
	// 通过on接口监听事件eventName
	// 如果事件eventName被触发,则执行callback回调函数
	on: function(eventName, callback) {
		//设置一个对象,存放所有的事件名和对应的事件处理函数
		if(this.obj===undefined){
			//this.obj = {};
			Object.defineProperty(this,"obj",{
				value:{},
				//设置为不可枚举,这样使用Object.assign就不能复制到他的值
				//实现了复制之后,相互之间的事件处理函数不影响
				enumerable:false
			})
		}
		//如果对象中不存在该事件名,则定义一个数组,存放该事件名的所有事件处理函数
		if(this.obj[eventName]===undefined){
			this.obj[eventName] = [callback];
		}else{
			this.obj[eventName].push(callback);
		}
					
	},
	//触发事件 eventName
	emit: function(eventName) {
		//如果存在该事件名
		if(this.obj[eventName]){
			//遍历,执行对应的事件处理函数
			for(var j = 0; j < this.obj[eventName].length; j++){
				this.obj[eventName][j](arguments[1]);
			}
		}
	}
};
			
			
// 测试1
			
Event.on('test', function(result) {
	console.log(result);
});
Event.on('test', function() {
	console.log('test');
});
			
Event.emit('test', 'hello world'); // 输出 'hello world' 和 'test'
			
			
		
// 测试2
var person1 = {};
var person2 = {};
			
Object.assign(person1, Event);
Object.assign(person2, Event);
			
			
			
person1.on('call1', function() {
	console.log('person1');
});
person2.on('call2', function() {
	console.log('person2');
});
	
person1.emit('call1'); // 输出 'person1'
person1.emit('call2'); // 没有输出
person2.emit('call1'); // 没有输出
person2.emit('call2'); // 输出 'person2'
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值