如何全面掌握JavaScript面试中由浅入深的知识点?
- 内容介绍
- 文章标签
- 相关推荐
本文共计3595个文字,预计阅读时间需要15分钟。
本章节为家长带来了关于JavaScript面试知识点的详细总结,涵盖66条JavaScript知识点,由浅入深,希望对家长有所帮助。
前言:我只想面见CV工程师,面试官偏偏让我挑战造火箭工程师。
本篇文章给大家带来了关于javascript面试知识点的详细总结,文章总结了66条JavaScript知识点由浅入深,希望对大家有帮助。前言
我只想面个CV工程师,面试官偏偏让我挑战造火箭工程师,加上今年这个情况更是前后两男,但再难苟且的生活还要继续,饭碗还是要继续找的。在最近的面试中我一直在总结,每次面试回来也都会复盘,下面是我这几天遇到的面试知识点。但今天主题是标题所写的66条JavaScript知识点,由浅入深,整理了一周,每(zhěng)天(lǐ)整(bù)理( yì)10条( qiú)左(diǎn)右(zàn), 希望对正在找工作的小伙伴有点帮助,文中如有表述不对,还请指出。
HTML&CSS:
- 浏览器内核
- 盒模型、flex布局、两/三栏布局、水平/垂直居中;
- BFC、清除浮动;
- css3动画、H5新特性。
JavaScript:
- 继承、原型链、this指向、设计模式、call, apply, bind,;
- new实现、防抖节流、let, var, const 区别、暂时性死区、event、loop;
- promise使用及实现、promise并行执行和顺序执行;
- async/await的优缺点;
- 闭包、垃圾回收和内存泄漏、数组方法、数组乱序, 数组扁平化、事件委托、事件监听、事件模型
Vue:
- vue数据双向绑定原理;
- vue computed原理、computed和watch的区别;
- vue编译器结构图、生命周期、vue组件通信;
- mvvm模式、mvc模式理解;
- vue dom diff、vuex、vue-router
网络:
- HTTP1, HTTP2, HTTPS、常见的xxxx.com/api/register">
用户名:<input type="text" name="userName">
密码:<input type="text" name="password">
手机号码:<input type="text" name="phoneNumber">
<button type="submit">提交</button>
</form>
<script type="text/javascript">
// 策略对象
const strategies = {
isNoEmpty: function (value, errorMsg) {
if (value === '') {
return errorMsg;
}
},
isNoSpace: function (value, errorMsg) {
if (value.trim() === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) {
if (value.trim().length < length) {
return errorMsg;
}
},
maxLength: function (value, length, errorMsg) {
if (value.length > length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) {
if (!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(value)) {
return errorMsg;
}
}
}
// 验证类
class Validator {
constructor() {
this.cache = []
}
add(dom, rules) {
for(let i = 0, rule; rule = rules[i++];) {
let strategyAry = rule.strategy.split(':')
let errorMsg = rule.errorMsg this.cache.push(() => {
let strategy = strategyAry.shift()
strategyAry.unshift(dom.value)
strategyAry.push(errorMsg)
return strategies[strategy].apply(dom, strategyAry)
})
}
}
start() {
for(let i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
let errorMsg = validatorFunc()
if (errorMsg) {
return errorMsg }
}
}
}
// 调用代码
let registerForm = document.getElementById('registerForm')
let validataFunc = function() {
let validator = new Validator()
validator.add(registerForm.userName, [{
strategy: 'isNoEmpty',
errorMsg: '用户名不可为空'
}, {
strategy: 'isNoSpace',
errorMsg: '不允许以空白字符命名'
}, {
strategy: 'minLength:2',
errorMsg: '用户名长度不能小于2位'
}])
validator.add(registerForm.password, [ {
strategy: 'minLength:6',
errorMsg: '密码长度不能小于6位'
}])
validator.add(registerForm.phoneNumber, [{
strategy: 'isMobile',
errorMsg: '请输入正确的手机号码格式'
}])
return validator.start()
}
registerForm.onsubmit = function() {
let errorMsg = validataFunc()
if (errorMsg) {
alert(errorMsg)
return false
}
}
</script></body></html>
场景例子
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的’行为’,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 表单验证
优点
- 利用组合、委托、多态等技术和思想,可以有效的避免多重条件选择语句
- 提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,理解,易于扩展
- 利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的代替方案
缺点
- 会在程序中增加许多策略类或者策略对象
- 要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy
6. 迭代器模式(Iterator Pattern)
如果你看到这,ES6中的迭代器 Iterator 相信你还是有点印象的,上面第60条已经做过简单的介绍。迭代器模式简单的说就是提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象的内部表示。
迭代器模式解决了以下问题:
- 提供一致的遍历各种数据结构的方式,而不用了解数据的内部结构
- 提供遍历容器(集合)的能力而无需改变容器的接口
一个迭代器通常需要实现以下接口:
- hasNext():判断迭代是否结束,返回Boolean
- next():查找并返回下一个元素
为Javascript的数组实现一个迭代器可以这么写:
const item = [1, 'red', false, 3.14];function Iterator(items) { this.items = items; this.index = 0;}Iterator.prototype = { hasNext: function () { return this.index < this.items.length; }, next: function () { return this.items[this.index++]; }}
验证一下迭代器是否工作:
const iterator = new Iterator(item);while(iterator.hasNext()){ console.log(iterator.next());} /输出:1, red, false, 3.14
ES6提供了更简单的迭代循环语法 for…of,使用该语法的前提是操作对象需要实现 可迭代协议(The iterable protocol),简单说就是该对象有个Key为 Symbol.iterator 的方法,该方法返回一个iterator对象。
比如我们实现一个 Range 类用于在某个数字区间进行迭代:
function Range(start, end) { return { [Symbol.iterator]: function () { return { next() { if (start < end) { return { value: start++, done: false }; } return { done: true, value: end }; } } } }}
验证一下:
for (num of Range(1, 5)) { console.log(num);}// 输出:1, 2, 3, 4
7. 观察者模式(Observer Pattern)
观察者模式又称发布-订阅模式(Publish/Subscribe Pattern),是我们经常接触到的设计模式,日常生活中的应用也比比皆是,比如你订阅了某个博主的频道,当有内容更新时会收到推送;又比如JavaScript中的事件订阅响应机制。观察者模式的思想用一句话描述就是:被观察对象(subject)维护一组观察者(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!
场景
- DOM事件
document.body.addEventListener('click', function() { console.log('hello world!');});document.body.click()
- vue 响应式
优点
- 支持简单的广播通信,自动通知所有已经订阅过的对象
- 目标对象与观察者之间的抽象耦合关系能单独扩展以及重用
- 增加了灵活性
- 观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。
缺点
- 过度使用会导致对象与对象之间的联系弱化,会导致程序难以跟踪维护和理解
8. 中介者模式(Mediator Pattern)
在中介者模式中,中介者(Mediator)包装了一系列对象相互作用的方式,使得这些对象不必直接相互作用,而是由中介者协调它们之间的交互,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。
中介者模式和观察者模式有一定的相似性,都是一对多的关系,也都是集中式通信,不同的是中介者模式是处理同级对象之间的交互,而观察者模式是处理Observer和Subject之间的交互。中介者模式有些像婚恋中介,相亲对象刚开始并不能直接交流,而是要通过中介去筛选匹配再决定谁和谁见面。
场景
- 例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
var goods = { //手机库存 'red|32G': 3, 'red|64G': 1, 'blue|32G': 7, 'blue|32G': 6,};//中介者var mediator = (function() { var colorSelect = document.getElementById('colorSelect'); var memorySelect = document.getElementById('memorySelect'); var numSelect = document.getElementById('numSelect'); return { changed: function(obj) { switch(obj){ case colorSelect: //TODO break; case memorySelect: //TODO break; case numSelect: //TODO break; } } }})();colorSelect.onchange = function() { mediator.changed(this);};memorySelect.onchange = function() { mediator.changed(this);};numSelect.onchange = function() { mediator.changed(this);};
- 聊天室里
聊天室成员类:
function Member(name) { this.name = name; this.chatroom = null;}Member.prototype = { // 发送消息 send: function (message, toMember) { this.chatroom.send(message, this, toMember); }, // 接收消息 receive: function (message, fromMember) { console.log(`${fromMember.name} to ${this.name}: ${message}`); }}
聊天室类:
function Chatroom() { this.members = {};}Chatroom.prototype = { // 增加成员 addMember: function (member) { this.members[member.name] = member; member.chatroom = this; }, // 发送消息 send: function (message, fromMember, toMember) { toMember.receive(message, fromMember); }}
测试一下:
const chatroom = new Chatroom(); const bruce = new Member('bruce'); const frank = new Member('frank'); chatroom.addMember(bruce);chatroom.addMember(frank); bruce.send('Hey frank', frank); //输出:bruce to frank: hello frank
优点
- 使各对象之间耦合松散,而且可以独立地改变它们之间的交互
- 中介者和对象一对多的关系取代了对象之间的网状多对多的关系
- 如果对象之间的复杂耦合度导致维护很困难,而且耦合度随项目变化增速很快,就需要中介者重构代码
缺点
- 系统中会新增一个中介者对象,因为对象之间交互的复杂性,转移成了中介者对象的复杂性,使得中介者对象经常是巨大的。中介 者对象自身往往就是一个难以维护的对象。
9. 访问者模式(Visitor Pattern)
访问者模式 是一种将算法与对象结构分离的设计模式,通俗点讲就是:访问者模式让我们能够在不改变一个对象结构的前提下能够给该对象增加新的逻辑,新增的逻辑保存在一个独立的访问者对象中。访问者模式常用于拓展一些第三方的库和工具。
// 访问者 class Visitor { constructor() {} visitConcreteElement(ConcreteElement) { ConcreteElement.operation() }}// 元素类 class ConcreteElement{ constructor() { } operation() { console.log("ConcreteElement.operation invoked"); } accept(visitor) { visitor.visitConcreteElement(this) }}// clientlet visitor = new Visitor()let element = new ConcreteElement()elementA.accept(visitor)
访问者模式的实现有以下几个要素:
- Visitor Object:访问者对象,拥有一个
visit()方法 - Receiving Object:接收对象,拥有一个
accept()方法 - visit(receivingObj):用于Visitor接收一个
Receiving Object - accept(visitor):用于
Receving Object接收一个Visitor,并通过调用Visitor的visit()为其提供获取Receiving Object数据的能力
简单的代码实现如下:
Receiving Object:function Employee(name, salary) { this.name = name; this.salary = salary;}Employee.prototype = { getSalary: function () { return this.salary; }, setSalary: function (salary) { this.salary = salary; }, accept: function (visitor) { visitor.visit(this); }}Visitor Object:function Visitor() { }Visitor.prototype = { visit: function (employee) { employee.setSalary(employee.getSalary() * 2); }}
验证一下:
const employee = new Employee('bruce', 1000); const visitor = new Visitor(); employee.accept(visitor);console.log(employee.getSalary()); //输出:2000
场景
- 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
优点
- 符合单一职责原则
- 优秀的扩展性
- 灵活性
缺点
- 具体元素对访问者公布细节,违反了迪米特原则
- 违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
- 具体元素变更比较困难
相关推荐:javascript学习教程
以上就是由浅入深详细整理JavaScript面试知识点的详细内容,更多请关注自由互联其它相关文章!
本文共计3595个文字,预计阅读时间需要15分钟。
本章节为家长带来了关于JavaScript面试知识点的详细总结,涵盖66条JavaScript知识点,由浅入深,希望对家长有所帮助。
前言:我只想面见CV工程师,面试官偏偏让我挑战造火箭工程师。
本篇文章给大家带来了关于javascript面试知识点的详细总结,文章总结了66条JavaScript知识点由浅入深,希望对大家有帮助。前言
我只想面个CV工程师,面试官偏偏让我挑战造火箭工程师,加上今年这个情况更是前后两男,但再难苟且的生活还要继续,饭碗还是要继续找的。在最近的面试中我一直在总结,每次面试回来也都会复盘,下面是我这几天遇到的面试知识点。但今天主题是标题所写的66条JavaScript知识点,由浅入深,整理了一周,每(zhěng)天(lǐ)整(bù)理( yì)10条( qiú)左(diǎn)右(zàn), 希望对正在找工作的小伙伴有点帮助,文中如有表述不对,还请指出。
HTML&CSS:
- 浏览器内核
- 盒模型、flex布局、两/三栏布局、水平/垂直居中;
- BFC、清除浮动;
- css3动画、H5新特性。
JavaScript:
- 继承、原型链、this指向、设计模式、call, apply, bind,;
- new实现、防抖节流、let, var, const 区别、暂时性死区、event、loop;
- promise使用及实现、promise并行执行和顺序执行;
- async/await的优缺点;
- 闭包、垃圾回收和内存泄漏、数组方法、数组乱序, 数组扁平化、事件委托、事件监听、事件模型
Vue:
- vue数据双向绑定原理;
- vue computed原理、computed和watch的区别;
- vue编译器结构图、生命周期、vue组件通信;
- mvvm模式、mvc模式理解;
- vue dom diff、vuex、vue-router
网络:
- HTTP1, HTTP2, HTTPS、常见的xxxx.com/api/register">
用户名:<input type="text" name="userName">
密码:<input type="text" name="password">
手机号码:<input type="text" name="phoneNumber">
<button type="submit">提交</button>
</form>
<script type="text/javascript">
// 策略对象
const strategies = {
isNoEmpty: function (value, errorMsg) {
if (value === '') {
return errorMsg;
}
},
isNoSpace: function (value, errorMsg) {
if (value.trim() === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) {
if (value.trim().length < length) {
return errorMsg;
}
},
maxLength: function (value, length, errorMsg) {
if (value.length > length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) {
if (!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(value)) {
return errorMsg;
}
}
}
// 验证类
class Validator {
constructor() {
this.cache = []
}
add(dom, rules) {
for(let i = 0, rule; rule = rules[i++];) {
let strategyAry = rule.strategy.split(':')
let errorMsg = rule.errorMsg this.cache.push(() => {
let strategy = strategyAry.shift()
strategyAry.unshift(dom.value)
strategyAry.push(errorMsg)
return strategies[strategy].apply(dom, strategyAry)
})
}
}
start() {
for(let i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
let errorMsg = validatorFunc()
if (errorMsg) {
return errorMsg }
}
}
}
// 调用代码
let registerForm = document.getElementById('registerForm')
let validataFunc = function() {
let validator = new Validator()
validator.add(registerForm.userName, [{
strategy: 'isNoEmpty',
errorMsg: '用户名不可为空'
}, {
strategy: 'isNoSpace',
errorMsg: '不允许以空白字符命名'
}, {
strategy: 'minLength:2',
errorMsg: '用户名长度不能小于2位'
}])
validator.add(registerForm.password, [ {
strategy: 'minLength:6',
errorMsg: '密码长度不能小于6位'
}])
validator.add(registerForm.phoneNumber, [{
strategy: 'isMobile',
errorMsg: '请输入正确的手机号码格式'
}])
return validator.start()
}
registerForm.onsubmit = function() {
let errorMsg = validataFunc()
if (errorMsg) {
alert(errorMsg)
return false
}
}
</script></body></html>
场景例子
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的’行为’,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 表单验证
优点
- 利用组合、委托、多态等技术和思想,可以有效的避免多重条件选择语句
- 提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,理解,易于扩展
- 利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的代替方案
缺点
- 会在程序中增加许多策略类或者策略对象
- 要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy
6. 迭代器模式(Iterator Pattern)
如果你看到这,ES6中的迭代器 Iterator 相信你还是有点印象的,上面第60条已经做过简单的介绍。迭代器模式简单的说就是提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象的内部表示。
迭代器模式解决了以下问题:
- 提供一致的遍历各种数据结构的方式,而不用了解数据的内部结构
- 提供遍历容器(集合)的能力而无需改变容器的接口
一个迭代器通常需要实现以下接口:
- hasNext():判断迭代是否结束,返回Boolean
- next():查找并返回下一个元素
为Javascript的数组实现一个迭代器可以这么写:
const item = [1, 'red', false, 3.14];function Iterator(items) { this.items = items; this.index = 0;}Iterator.prototype = { hasNext: function () { return this.index < this.items.length; }, next: function () { return this.items[this.index++]; }}
验证一下迭代器是否工作:
const iterator = new Iterator(item);while(iterator.hasNext()){ console.log(iterator.next());} /输出:1, red, false, 3.14
ES6提供了更简单的迭代循环语法 for…of,使用该语法的前提是操作对象需要实现 可迭代协议(The iterable protocol),简单说就是该对象有个Key为 Symbol.iterator 的方法,该方法返回一个iterator对象。
比如我们实现一个 Range 类用于在某个数字区间进行迭代:
function Range(start, end) { return { [Symbol.iterator]: function () { return { next() { if (start < end) { return { value: start++, done: false }; } return { done: true, value: end }; } } } }}
验证一下:
for (num of Range(1, 5)) { console.log(num);}// 输出:1, 2, 3, 4
7. 观察者模式(Observer Pattern)
观察者模式又称发布-订阅模式(Publish/Subscribe Pattern),是我们经常接触到的设计模式,日常生活中的应用也比比皆是,比如你订阅了某个博主的频道,当有内容更新时会收到推送;又比如JavaScript中的事件订阅响应机制。观察者模式的思想用一句话描述就是:被观察对象(subject)维护一组观察者(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!
场景
- DOM事件
document.body.addEventListener('click', function() { console.log('hello world!');});document.body.click()
- vue 响应式
优点
- 支持简单的广播通信,自动通知所有已经订阅过的对象
- 目标对象与观察者之间的抽象耦合关系能单独扩展以及重用
- 增加了灵活性
- 观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。
缺点
- 过度使用会导致对象与对象之间的联系弱化,会导致程序难以跟踪维护和理解
8. 中介者模式(Mediator Pattern)
在中介者模式中,中介者(Mediator)包装了一系列对象相互作用的方式,使得这些对象不必直接相互作用,而是由中介者协调它们之间的交互,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。
中介者模式和观察者模式有一定的相似性,都是一对多的关系,也都是集中式通信,不同的是中介者模式是处理同级对象之间的交互,而观察者模式是处理Observer和Subject之间的交互。中介者模式有些像婚恋中介,相亲对象刚开始并不能直接交流,而是要通过中介去筛选匹配再决定谁和谁见面。
场景
- 例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
var goods = { //手机库存 'red|32G': 3, 'red|64G': 1, 'blue|32G': 7, 'blue|32G': 6,};//中介者var mediator = (function() { var colorSelect = document.getElementById('colorSelect'); var memorySelect = document.getElementById('memorySelect'); var numSelect = document.getElementById('numSelect'); return { changed: function(obj) { switch(obj){ case colorSelect: //TODO break; case memorySelect: //TODO break; case numSelect: //TODO break; } } }})();colorSelect.onchange = function() { mediator.changed(this);};memorySelect.onchange = function() { mediator.changed(this);};numSelect.onchange = function() { mediator.changed(this);};
- 聊天室里
聊天室成员类:
function Member(name) { this.name = name; this.chatroom = null;}Member.prototype = { // 发送消息 send: function (message, toMember) { this.chatroom.send(message, this, toMember); }, // 接收消息 receive: function (message, fromMember) { console.log(`${fromMember.name} to ${this.name}: ${message}`); }}
聊天室类:
function Chatroom() { this.members = {};}Chatroom.prototype = { // 增加成员 addMember: function (member) { this.members[member.name] = member; member.chatroom = this; }, // 发送消息 send: function (message, fromMember, toMember) { toMember.receive(message, fromMember); }}
测试一下:
const chatroom = new Chatroom(); const bruce = new Member('bruce'); const frank = new Member('frank'); chatroom.addMember(bruce);chatroom.addMember(frank); bruce.send('Hey frank', frank); //输出:bruce to frank: hello frank
优点
- 使各对象之间耦合松散,而且可以独立地改变它们之间的交互
- 中介者和对象一对多的关系取代了对象之间的网状多对多的关系
- 如果对象之间的复杂耦合度导致维护很困难,而且耦合度随项目变化增速很快,就需要中介者重构代码
缺点
- 系统中会新增一个中介者对象,因为对象之间交互的复杂性,转移成了中介者对象的复杂性,使得中介者对象经常是巨大的。中介 者对象自身往往就是一个难以维护的对象。
9. 访问者模式(Visitor Pattern)
访问者模式 是一种将算法与对象结构分离的设计模式,通俗点讲就是:访问者模式让我们能够在不改变一个对象结构的前提下能够给该对象增加新的逻辑,新增的逻辑保存在一个独立的访问者对象中。访问者模式常用于拓展一些第三方的库和工具。
// 访问者 class Visitor { constructor() {} visitConcreteElement(ConcreteElement) { ConcreteElement.operation() }}// 元素类 class ConcreteElement{ constructor() { } operation() { console.log("ConcreteElement.operation invoked"); } accept(visitor) { visitor.visitConcreteElement(this) }}// clientlet visitor = new Visitor()let element = new ConcreteElement()elementA.accept(visitor)
访问者模式的实现有以下几个要素:
- Visitor Object:访问者对象,拥有一个
visit()方法 - Receiving Object:接收对象,拥有一个
accept()方法 - visit(receivingObj):用于Visitor接收一个
Receiving Object - accept(visitor):用于
Receving Object接收一个Visitor,并通过调用Visitor的visit()为其提供获取Receiving Object数据的能力
简单的代码实现如下:
Receiving Object:function Employee(name, salary) { this.name = name; this.salary = salary;}Employee.prototype = { getSalary: function () { return this.salary; }, setSalary: function (salary) { this.salary = salary; }, accept: function (visitor) { visitor.visit(this); }}Visitor Object:function Visitor() { }Visitor.prototype = { visit: function (employee) { employee.setSalary(employee.getSalary() * 2); }}
验证一下:
const employee = new Employee('bruce', 1000); const visitor = new Visitor(); employee.accept(visitor);console.log(employee.getSalary()); //输出:2000
场景
- 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
优点
- 符合单一职责原则
- 优秀的扩展性
- 灵活性
缺点
- 具体元素对访问者公布细节,违反了迪米特原则
- 违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
- 具体元素变更比较困难
相关推荐:javascript学习教程
以上就是由浅入深详细整理JavaScript面试知识点的详细内容,更多请关注自由互联其它相关文章!

