关于9-6订阅发布的几个问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 观察者
var observer = {
// 订阅集合
subscribes: [],
// 订阅
subscribe: function (type, fn) {
if (!this.subscribes[type]) {
this.subscribes[type] = [];
}
// 收集订阅者的处理
typeof fn === "function" && this.subscribes[type].push(fn);
},
// 发布 可能会携带一些信息发布出去
publish: function () {
var type = [].shift.call(arguments),
fns = this.subscribes[type];
// 不存在的订阅类型,以及订阅时未传入处理回调的
if (!fns || !fns.length) {
return;
}
// 挨个处理调用
for (var i = 0; i < fns.length; ++i) {
fns[i].apply(this, arguments);
}
},
// 删除订阅
remove: function (type, fn) {
// 删除全部
if (typeof type === "undefined") {
this.subscribes = [];
return;
}
var fns = this.subscribes[type];
// 不存在的订阅类型,以及订阅时未传入处理回调的
if (!fns || !fns.length) {
return;
}
if (typeof fn === "undefined") {
fns.length = 0;
return;
}
// 挨个处理删除
for (var i = 0; i < fns.length; ++i) {
if (fns[i] === fn) {
fns.splice(i, 1);
}
}
},
};
// 订阅岗位列表
function jobListForA(jobs) {
console.log("A", jobs);
}
function jobListForB(jobs) {
console.log("B", jobs);
}
// A订阅了岗位
observer.subscribe("job", jobListForA);
// B订阅了岗位
observer.subscribe("job", jobListForB);
// A订阅了笔试成绩
observer.subscribe("examinationA", function (score) {
console.log(score);
});
// B订阅了笔试成绩
observer.subscribe("examinationB", function (score) {
console.log(score);
});
// A订阅了面试结果
observer.subscribe("interviewA", function (result) {
console.log(result);
});
observer.publish("examinationA", 100); // 100
observer.publish("examinationB", 80); // 80
observer.publish("interviewA", "备用"); // 备用
observer.publish("job", ["前端", "后端", "测试"]); // 输出A和B的岗位
// B取消订阅了笔试成绩
observer.remove("examinationB");
// A取消订阅了岗位
observer.remove("job", jobListForA);
observer.publish("examinationB", 80); // 没有可匹配的订阅,无输出
observer.publish("job", ["前端", "后端", "测试"]); // 输出B的岗位
</script>
</body>
</html>
1、
var type = [].shift.call(arguments)不太理解这个用法
我试了几次,结果是删除arguments的第一项,并且返回第一项组成的数组
2、
// B取消订阅了笔试成绩
observer.remove("examinationB");
正常执行
//A取消订阅了岗位 observer.remove('job', jobListForA);
不太正常的部分
// B取消订阅了笔试成绩 observer.remove('examinationB');
经过这里的时候,fns已经被清空了,
而且注释写的是处理订阅时未传入处理回调函数,这一部分不是应该写在订阅里面吗?
其他部分都能明白,两个部分请老师详细讲一下,谢谢
正在回答
同学你好,解答如下:
1、[].shift.call(arguments)是一个固定语法,在这里主要用来获取arguments中的第一项。arguments是类似数组的形式,可以通过打印帮助我们理解这一步的操作:
初始的arguments中有两项内容:
this.subscribes中存储的是“订阅内容(订阅事件名):订阅内容(订阅事件名)对应的处理函数”,比如订阅examinationA时,subscribes中存储的格式如下:
所以想获取“examinationA”的事件处理程序,则需要获取“examinationA”这个事件名,再从subscribes中获取它对应的事件处理程序(这里数组的用法,类似于对象),即:
通过[].shift.call处理后,最初的arguments中,删除了“examinationA”这个事件名,那就只剩下了100:
这个100,则是传给“事件处理程序的真实数据”:
2、第二问,不是很明白同学表达的意思。给同学简单说一下,看能否解答疑惑:
a、observer.remove("examinationB")这句代码清除的fns,只是清除了examinationB这个事件对应的事件处理程序,不会清除其他事件对应的事件处理程序。将所有代码还原,我们看一下subscribes的内容:
注意,同一个事件的处理程序,可能有多个,比如job:
当删除订阅的时候,会将对应的事件处理函数删除,其余的都保留,比如:
b、逻辑写在哪里,看个人理解。如果同学觉得“订阅时未传入事件处理回调函数”这种情况是错误的,那么可以在订阅里面严格控制一下。如果程序宽松一点,允许这种情况存在,那么可以不写在订阅中。毕竟订阅会有好多次,“第一次订阅事件A,没有传入对应程序”,但是第二次订阅事件A,传入了对应程序,那么可以不在订阅里面控制,如下这种行为,也可以:
祝学习愉快!
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星