面向对象-原型,实例,构造函数

一、设计:设计原则 模式:设计模式
设计原则:
1、单一职责
2、开闭原则
3、里氏替换
4、迪米特法则
5、接口隔离
6、依赖倒置
单例模式-高阶函数

<script type='module'>
	// 单例模式,高阶函数,函数作为参数输出,或者输出函数
	import Person from './object2.js'
	function getSingle(fn){
		let instance
		return function (...arg){
			if(!instance){
				instance = new fn(...arg)
			}
			return instance
		}
	}
	let createSingleFn = getSingle(Person)
	let joy = createSingleFn('joy')
	let tom = createSingleFn('tom')
	console.log(joy, tom) // joy
</script>

工厂函数
根据不同的参数,生成不同的实例

class Luban{
	constructor(){
		this.name = 'luban'
	}
}
class Yase{
	constructor() {
	    this.name = 'yase'
	}
}
function Factory(heroName){
	if(heroName == 'luban'){
		return new Luban()
	}
	if(heroName == 'Yase'){
		return new Yase()
	}
}
// 工厂函数,根据不同的参数,生成不同的对象实例
console.log(Factory('luban'))
console.log(Factory('Yase'))

装饰者模式

class Hero{
	constructor() {
	    this.name = 'yase'
	}
	fire(){
		console.log('释放了技能')
	}
}
function hurt(num){
	console.log('造成了' + num + '伤害')
}
// 装饰着模式
// 在方法的原型上面添加Decorator方法,让每一个方法都有一个装饰者方法
Function.prototype.Decorator = function (fn, ...arg){
	this() // 执行Function方法,即执行被装饰的方法先执行一遍
	fn(...arg) // 参数方法 的执行,该方法传入..arg里面的参数
}
// 获取实例
let yase = new Hero()
// 获取实例方法,并且传入要装饰的方法和参数
yase.fire.Decorator(hurt, 100)

自定义事件
index.html

<script type='module'>
	import './object2.js'
</script>

index.js

export default class myEvent{
	constructor() {
	    this.handle = {}
	}
	addEvent(eventName, fn){
		if(typeof this.handle[eventName] === 'undefined'){
			this.handle[eventName] = []
		}
		this.handle[eventName].push(fn)
	}
	trigger(eventName){
		this.handle[eventName].forEach(fn => {
			fn()
		})
	}
	removeEvent(eventName, fn){
		let fns = this.handle[eventName]
		let index
		if((index = fns.indexOf(fn)) !== -1){
			fns.splice(index, 1)
		}
	}
}
function fn1(){
	console.log('fn1...')
}
function fn2(){
	console.log('fn2...')
} 
function fn3(){
	console.log('fn3...')
}
let events = new myEvent()
events.addEvent('myEvent', fn1)
events.addEvent('myEvent', fn2)
events.addEvent('myEvent', fn3)
events.removeEvent('myEvent', fn2)
events.trigger('myEvent') // fn1  fn3

二、面向对象的编程思想

  • 面向过程: 注重解决问题的步骤,分析问题需要的每一步,实现函数一次调用
  • 面向对象: 是一种程序设计思想。将数据和处理数据的程序封装到对象中。
  • 面向对象特性: 抽象、继承、封装、多态
    优点: 提高代码的复用性及可维护性。
    1.对象的创建
    1.1对象字面量
let obj = {
	name: 'joy',
	age: 15,
	hobby: function (){
		console.log('swim')
	}
}
console.log(obj) // obj{name: 'joy'...}

1.2构造函数

let obj = new Object()
obj.name = 'joy'
obj.age = 17
obj.hobby = function (){
	console.log('swim')
}
console.log(obj) // obj{name : 'joy' ...}

1.3Object.create() 属性方法放在原型上

let str = 'sex'
let obj = Object.create({
	name: 'joy',
	[str]: 'man', 
	age: 15,
	hobby(){
		console.log('swim')
	}
})
console.log(obj) // 属性在原型上
console.log(obj[str]) // 'man'

2.工厂模式

//工厂模式
function Person(name, age, hobby){
	let obj = {} // 添加原料
	obj.name = name
	obj.age = age 
	obj.hobby = hobby 
	// 加工
	return obj // 返回成品,
}
let joy = Person('joy', '14', 'swim')
console.log(joy) // {name: 'joy', age: 14, hobby: 'swim'}

3.原型

Person.prototype.fn2 = () => {
	console.log('fn2')
}
function Person(name){
	this.name = name
	this.fn = () => {
		console.log('fn')
	}
}
let joy = new Person('joy')
let tom = new Person('tom')
console.log(joy.fn === tom.fn) // false 虽然函数一样,但是函数地址不一样,存在不同空间
console.log(joy.fn2 === tom.fn2) // true 在同一空间存储内容,更节约性能
console.log(joy.__proto__ === Person.prototype) // true
console.log(joy.constructor === Person) // true 系统自己在原型上指定了来自哪个构造函数

4.原型、实例、构造函数三者的关系

let temp 
function Person(name){
	this.name = name
	this.age = 20
	//temp = this
}
// 如果这里使用箭头函数,this就会指向其父级
Person.prototype.fn = function() {
	console.log(1)
	temp = this
}
console.log(Person.prototype.constructor === Person) // true
// 构造函数里面的this指向实例对象
// 原型上面的方法里面的this也指向实例化对象,如果用了箭头函数,this指向其父级
let joy = new Person('joy')
joy.fn()
console.log(temp)
console.log(joy === temp) // true

5.call,apply,bind

function foo(name, age){
	console.log('姓名是' + this.name + ',年龄是' + age)
	console.log(this)
}
let obj = {
	name: 'joy'
}
//foo.call(obj, 'tom', 16) // joy
//foo.apply(obj,['tom', 15]) // joy
foo.bind(obj)('tom', 13) // 返回的是一个函数,需要传参执行或者直接执行 joy

6.深拷贝

let obj = {
	name: 'joy',
	age: '15',
	son: {
		name: 'you',
		age: 1
	},
	test: undefined,
	hobby(){
		console.log('swim')
	}
}
// 用JSON可以进行深拷贝,但是会丢失undefined和方法属性
//let obj2 = JSON.parse(JSON.stringify(obj))
let obj2 = deepCopy(obj)
obj2.son.sex = 'man'
console.log(obj2) 
console.log(obj)
// 自定义深拷贝函数
function deepCopy(obj){
	// 判断如果obj是对象的话,就分别创建{}和[]
	let newObj = Array.isArray(obj) ? [] : {};
	// 遍历
	for(let prop in obj){
		// for in 也会遍历父级的属性,需要判断该属性是不是自己的
		if(obj.hasOwnProperty(prop)){
			if(typeof obj[prop] === 'object'){
				// 如果是对象,递归
				newObj[prop] = deepCopy(obj[prop])
			}else{
				// 否则直接赋值
				newObj[prop] = obj[prop]
			}
		}
	}
	return newObj
}
// 原型继承也可以用深拷贝
Son.prototype = deepCopy(Dad.prototype)
// 可以达到父子之间的有独立的方法和属性
// 或者以下方法也可以解决父原型与子原型的同地址问题
let link = function (){}
link.prorotype = Dad.prototype
Son.prototype = new link()
// 把构造函数指向重新指向Son
Son.prototype.constructor = Son


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值