关于9-6订阅发布的几个问题

关于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");

https://img1.sycdn.imooc.com//climg/64f9cfb60944bf9f09221390.jpg

正常执行

//A取消订阅了岗位 observer.remove('job', jobListForA);


不太正常的部分

// B取消订阅了笔试成绩 observer.remove('examinationB');

经过这里的时候,fns已经被清空了,

而且注释写的是处理订阅时未传入处理回调函数,这一部分不是应该写在订阅里面吗?


其他部分都能明白,两个部分请老师详细讲一下,谢谢











正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学你好,解答如下:

1、[].shift.call(arguments)是一个固定语法,在这里主要用来获取arguments中的第一项。arguments是类似数组的形式,可以通过打印帮助我们理解这一步的操作:

https://img1.sycdn.imooc.com//climg/64fa7f3f0987c5b909820940.jpg

初始的arguments中有两项内容:

https://img1.sycdn.imooc.com//climg/64fa802a09668afe13110415.jpg

this.subscribes中存储的是“订阅内容(订阅事件名):订阅内容(订阅事件名)对应的处理函数”,比如订阅examinationA时,subscribes中存储的格式如下:

https://img1.sycdn.imooc.com//climg/64fa80a509f05b5809100916.jpg

https://img1.sycdn.imooc.com//climg/64fa811709e5e80407050105.jpg

所以想获取“examinationA”的事件处理程序,则需要获取examinationA”这个事件名,再从subscribes中获取它对应的事件处理程序(这里数组的用法,类似于对象),即:

https://img1.sycdn.imooc.com//climg/64fa81de093f3a3310950333.jpg

通过[].shift.call处理后,最初的arguments中,删除了examinationA”这个事件名,那就只剩下了100:

https://img1.sycdn.imooc.com//climg/64fa823d09c545c408990125.jpg

这个100,则是传给“事件处理程序的真实数据”:

https://img1.sycdn.imooc.com//climg/64fa827f09d8ac2c11510714.jpg

2、第二问,不是很明白同学表达的意思。给同学简单说一下,看能否解答疑惑:

 a、observer.remove("examinationB")这句代码清除的fns,只是清除了examinationB这个事件对应的事件处理程序,不会清除其他事件对应的事件处理程序。将所有代码还原,我们看一下subscribes的内容:

https://img1.sycdn.imooc.com//climg/64fa83c709c195d809300472.jpg

https://img1.sycdn.imooc.com//climg/64fa849e0902795e11140226.jpg

注意,同一个事件的处理程序,可能有多个,比如job:

https://img1.sycdn.imooc.com//climg/64fa84e909c3fbff09240390.jpg

当删除订阅的时候,会将对应的事件处理函数删除,其余的都保留,比如:

https://img1.sycdn.imooc.com//climg/64fa854e09a833c410060197.jpg

https://img1.sycdn.imooc.com//climg/64fa858609a0089808200290.jpg

b、逻辑写在哪里,看个人理解。如果同学觉得“订阅时未传入事件处理回调函数”这种情况是错误的,那么可以在订阅里面严格控制一下。如果程序宽松一点,允许这种情况存在,那么可以不写在订阅中。毕竟订阅会有好多次,“第一次订阅事件A,没有传入对应程序”,但是第二次订阅事件A,传入了对应程序,那么可以不在订阅里面控制,如下这种行为,也可以:

https://img1.sycdn.imooc.com//climg/64fa869c09500e3a11660334.jpg

祝学习愉快!

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师