作为一名优秀的前端需要了解哪几种设计模式?

console.log(anotherPerson.proto) //{name: “hello”, age: 24}

anotherPerson.name = ‘world’; //可以修改属性

anotherPerson.job = ‘teacher’;

另外,如果我们想要自己实现原型模式,而不是使用封装好的Object.create()函数,那么可以使用原型继承来实现

function F(){}

F.prototype.g = function(){}

//G类继承F类

function G(){

F.call(this);

}

//原型继承

function Fn(){};

Fn.prototype = F.prototype;

G.prototype = new Fn();

G.prototype.constructor = G;

原型模式就是创建一个指定原型的对象。如果我们需要重复创建某个对象,那么就可以使用原型模式来实现。


结构型模式


1. 装饰器模式

装饰器模式:为对象添加新功能,不改变其原有的结构和功能。

适配器模式是原有的不能用了,要重新封装接口。装饰器模式是原有的还能用,但是需要新增一些东西来完善这个功能。

比如手机壳,手机本身的功能不受影响,手机壳就是手机的装饰器模式。

装饰器模式

class Circle {

draw() {

console.log(‘画一个圆形’);

}

}

class Decorator {

constructor(circle) {

this.circle = circle;

}

draw() {

this.circle.draw();

this.setRedBorder(circle);

}

setRedBorder(circle) {

console.log(‘设置红色边框’)

}

}

// 测试

let circle = new Circle();

let client = new Decorator(circle);

client.draw();

输出结果:

画一个圆形

设置红色边框

如今都2021了,es7也应用广泛,我们在es7中这么写(ES7装饰器):

1、安装 yarn add babel-plugin-transform-decorators-legacy

2、新建.babelrc文件,进行下面的配置

{

“presets”: [“es2015”, “latest”],

“plugins”: [“transform-decorators-legacy”]

}

3、上代码

@testDec

class Demo {

// …

}

function testDec(target) {

target.isDec = true

}

console.log(Demo.isDec)

//输出true

打印出来了true,说明@testDec这个装饰器已经成功了,函数是个装饰器,用@testDec给Demo装饰了一遍。这个target其实就是class Demo,然后给她加一个isDec。

拆解后就是下面的内容:

// 装饰器原理

@decorator

class A {}

// 等同于

class A {}

A = decorator(A) || A;

装饰器参数的形式

@testDec(false)

class Demo {

}

function testDec(isDec) {

return function (target) {

target.isDec = isDec

}

}

console.log(Demo.isDec);

验证是否是一个真正的装饰器模式需要验证以下几点:

1.将现有对戏那个和装饰器进行分离,两者独立存在

2.符合开放封闭原则

2. 适配器模式

适配器模式:旧接口格式和使用者不兼容,中间加一个适配转换接口。

比如国外的插座跟国内的插座不一样,我们需要买个转换器去兼容。

适配器模式

上代码:

class Adaptee {

specificRequest() {

return ‘德国标准的插头’;

}

}

class Target {

constructor() {

this.adaptee = new Adaptee();

}

request() {

let info = this.adaptee.specificRequest();

return ${info} -> 转换器 -> 中国标准的插头

}

}

// 测试

let client = new Target();

client.request();

结果:

德国标准的插头 -> 转换器 -> 中国标准的插头

场景上可封装旧接口:

// 自己封装的ajax,使用方式如下:

ajax({

url: ‘/getData’,

type: ‘Post’,

dataType: ‘json’,

data: {

id: ‘123’

}

}).done(function(){

})

// 但因为历史原因,代码中全都是:

// $.ajax({…})

这个时候需要一个适配器

// 做一层适配器

var $ = {

ajax: function (options) {

return ajax(options)

}

}

3. 代理模式

代理模式:使用者无权访问目标对象,中间加代理,通过代理做授权和控制。

明星经纪人:比如有个演出,要请明星,要先联系经纪人。

或者理解为:为一个对象提供一个代用品或者占位符,以便控制对它的访问。例如图片懒加载、中介等。代理模式

/**

  • pre:代理模式

  • 小明追求A,B是A的好朋友,小明比不知道A什么时候心情好,不好意思直接将花交给A,

  • 于是小明将花交给B,再由B交给A.

*/

// 花的类

class Flower{

constructor(name){

this.name = name

}

}

// 小明拥有sendFlower的方法

let Xioaming = {

sendFlower(target){

var flower = new Flower(“玫瑰花”)

target.receive(flower)

}

}

// B对象中拥有接受花的方法,同时接收到花之后,监听A的心情,并且传入A心情好的时候函数

let B = {

receive(flower){

this.flower =flower

A.listenMood(()=>{

A.receive(this.flower)

})

}

}

// A接收到花之后输出花的名字

let A = {

receive(flower){

console.log(A收到了${flower.name} )

// A收到了玫瑰花

},

listenMood(func){

setTimeout(func,1000)

}

}

Xioaming.sendFlower(B)

虚拟代理用于图片的预加载

图片很大,页面加载时会空白,体验不好,所以我们需要个占位符,来短暂替代这个图片,等图片加载好了放上去。

let myImage = (function(){

let img = new Image

document.body.appendChild(img)

return {

setSrc:(src)=>{

img.src = src

}

}

})()

let imgProxy =(function(){

let imgProxy = new Image

// 这个地方我使用了setTimeout来增强演示效果,否则本地加载太快,根本看不到。

imgProxy.οnlοad=function(){

setTimeout(()=>{

myImage.setSrc(this.src)

},2000)

}

return (src)=>{

myImage.setSrc(“…/…/img/bgimg.jpeg”)

imgProxy.src=src

}

})()

imgProxy(“…/…/img/background-cover.jpg”)

ES6 Proxy

其实在ES6中,已经有了Proxy,这个内置的函数。我们来用一个例子来演示一下他的用法。这是一个明星代理的问题。

let star={

name : “张XX”,

age:25,

phone : “1300001111”

}

let agent = new Proxy(star,

{

get:function(target,key){

if(key === “phone”){

return “18839552597”

}else if(key === “name”){

return “张XX”

}else if(key === “price”){

return “12W”

}else if(key === “customPrice”){

return target.customPrice

}

},

set:function(target,key,value){

if(key === “customPrice”){

if(value < “10”){

console.log(“太低了!!!”)

return false

}else{

target[key] = value

return true

}

}

}

}

)

console.log(agent.name)

console.log(agent.price)

console.log(agent.phone)

console.log(agent.age)

agent.customPrice = “12”

console.log(agent)

console.log(agent.customPrice)

设计原则验证

代理类和目标类分离,隔离开目标类和使用者

符合开放封闭原则


行为型模式


1. 策略模式

策略模式是一种简单却常用的设计模式,它的应用场景非常广泛。我们先了解下策略模式的概念,再通过代码示例来更清晰的认识它。

策略模式由两部分构成:一部分是封装不同策略的策略组,另一部分是 Context。通过组合和委托来让 Context 拥有执行策略的能力,从而实现可复用、可扩展和可维护,并且避免大量复制粘贴的工作。

策略模式

策略模式的典型应用场景是表单校验中,对于校验规则的封装。接下来我们就通过一个简单的例子具体了解一下:

/**

  • 登录控制器

*/

function LoginController() {

this.strategy = undefined;

this.setStrategy = function (strategy) {

this.strategy = strategy;

this.login = this.strategy.login;

}

}

/**

  • 用户名、密码登录策略

*/

function LocalStragegy() {

this.login = ({ username, password }) => {

console.log(username, password);

// authenticating with username and password…

}

}

/**

  • 手机号、验证码登录策略

*/

function PhoneStragety() {

this.login = ({ phone, verifyCode }) => {

console.log(phone, verifyCode);

// authenticating with hone and verifyCode…

}

}

/**

  • 第三方社交登录策略

*/

function SocialStragety() {

this.login = ({ id, secret }) => {

console.log(id, secret);

// authenticating with id and secret…

}

}

const loginController = new LoginController();

// 调用用户名、密码登录接口,使用LocalStrategy

app.use(‘/login/local’, function (req, res) {

loginController.setStrategy(new LocalStragegy());

loginController.login(req.body);

});

// 调用手机、验证码登录接口,使用PhoneStrategy

app.use(‘/login/phone’, function (req, res) {

loginController.setStrategy(new PhoneStragety());

loginController.login(req.body);

});

// 调用社交登录接口,使用SocialStrategy

app.use(‘/login/social’, function (req, res) {

loginController.setStrategy(new SocialStragety());

loginController.login(req.body);

});

从以上示例可以得出使用策略模式有以下优势:

  1. 方便在运行时切换算法和策略

  2. 代码更简洁,避免使用大量的条件判断

  3. 关注分离,每个strategy类控制自己的算法逻辑,strategy和其使用者之间也相互独立

2. 观察者模式

观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一或一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。典型代表vue/react等。

使用观察者模式的好处:

  1. 支持简单的广播通信,自动通知所有已经订阅过的对象。

  2. 目标对象与观察者存在的是动态关联,增加了灵活性。

  3. 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。

观察者模式当然给元素绑定事件的addEventListener()也是一种:

target.addEventListener(type, listener [, options]);

Target就是被观察对象Subject,listener就是观察者Observer。

观察者模式中Subject对象一般需要实现以下API:

  • subscribe(): 接收一个观察者observer对象,使其订阅自己

  • unsubscribe(): 接收一个观察者observer对象,使其取消订阅自己

  • fire(): 触发事件,通知到所有观察者

用JavaScript手动实现观察者模式:

// 被观察者

function Subject() {

this.observers = [];

}

Subject.prototype = {

// 订阅

subscribe: function (observer) {

this.observers.push(observer);

},

// 取消订阅

unsubscribe: function (observerToRemove) {

this.observers = this.observers.filter(observer => {

return observer !== observerToRemove;

})

},

// 事件触发

fire: function () {

this.observers.forEach(observer => {

observer.call();

});

}

}

验证一下订阅是否成功:

const subject = new Subject();

function observer1() {

console.log(‘Observer 1 Firing!’);

}

function observer2() {

console.log(‘Observer 2 Firing!’);

}

subject.subscribe(observer1);

subject.subscribe(observer2);

subject.fire();

输出:

Observer 1 Firing!

Observer 2 Firing!

验证一下取消订阅是否成功:

subject.unsubscribe(observer2);

subject.fire();

输出:

Observer 1 Firing!

3. 迭代器模式

ES6中的迭代器 Iterator 相信大家都不陌生,迭代器用于遍历容器(集合)并访问容器中的元素,而且无论容器的数据结构是什么(Array、Set、Map等),迭代器的接口都应该是一样的,都需要遵循 迭代器协议

迭代器模式解决了以下问题:

  1. 提供一致的遍历各种数据结构的方式,而不用了解数据的内部结构

  2. 提供遍历容器(集合)的能力而无需改变容器的接口

迭代器模式

一个迭代器通常需要实现以下接口:

  • hasNext():判断迭代是否结束,返回Boolean

  • next():查找并返回下一个元素

为Javascript的数组实现一个迭代器可以这么写:

const item = [1, ‘red’, false, 3.14];

function Iterator(items) {

this.items = items;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)


前端面试题汇总


前端面试题是我面试过程中遇到的面试题,每一次面试后我都会复盘总结。我做了一个整理,并且在技术博客找到了专业的解答,大家可以参考下:

由于篇幅有限,只能分享部分面试题,完整版面试题及答案可以【点击我】阅读下载哦~无偿分享给大家

感悟

**

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-mpnoYVqv-1713669456234)]

[外链图片转存中…(img-eLugHw97-1713669456234)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-r1w9g7UJ-1713669456234)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

[外链图片转存中…(img-tfhKwO4T-1713669456235)]
前端面试题汇总


前端面试题是我面试过程中遇到的面试题,每一次面试后我都会复盘总结。我做了一个整理,并且在技术博客找到了专业的解答,大家可以参考下:

由于篇幅有限,只能分享部分面试题,完整版面试题及答案可以【点击我】阅读下载哦~无偿分享给大家

感悟

春招面试的后期,运气和实力都很重要,自己也是运气比较好,为了回馈粉丝朋友们(毕竟自己也玩了这么久哈哈哈),整理个人感悟和总结以上。最后祝愿大家能够收获理想offer!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值