原生JS技巧(2)浅谈回调函数(拦截器、注入和控制反转原理)

  现在很多框架都在说拦截器、依赖注入、控制反转,尤其是java,很多的js框架也引入这种设计思想,包括angular、vue等等,在网上一查也有好多关于这方面的文章,但技术性有很深,但读过源码的人应该就明白它核心的原理,由大到小来解释就是“回调函数”。

1、回调函数

  什么是“回调函数”,看下面例子

1 var list = [{a:1,b:2,c:3},{a:3,b:4,c:5},{a:4,b:3,c:2},{a:7,b:1,c:1}];
2 list.filter(function(item){
3 return item.a > 3;
4 });

filter是Array的一个函数,正常我们会list.filter()这么调用,来筛选数组,

如果所有的逻辑都写在filter()内部,我们需要大量的判断条件,在不清楚list数组内容的情况,就无法去写filter的条件,

这样我们就需要把控制权交给外面,里面只提供基础功能,用于返回新数组。

那我们自己写一个回调,如下:

1 var filter = function(array,callback){
2 var _array = [];
3 for(var i in array){
4 if(callback.call(this,array[i])) _array.push(array[i]);
5 }
6 }

由此能看出,回调函数就是参数只传入一个函数体,而函数内部执行作为参数的这个函数。

 

2、拦截器

很多语言都有拦截器,而拦截器的原理和回调函数很像,也是把部分的控制权交给了外部,而内部只是调用包含外部控制权的函数

var c = function(callback){
    var b = 0;
    setInterval(function(){
        b += 1;
        if(b % 3 === 0){
            callback.apply(this,[b*1000]);
        }
    },1000)
}
var a = [];
c(function(val){
    a.push(val);
});

a的值: [3000, 6000, 9000, ...] ,会按照每3秒的时间拦截一次,并向a数组中添加

我们在外部可以任意定义callback中的逻辑,如果c函数内部是一个ajax请求或其他异步,我们需要捕捉请求回来时变量被赋值,或者捕捉模块加载完成时,都可以在需要的节点下调用一个回调函数,并把内部获取的数据通过参数返回给外部,像:callback.apply(this指向的对象,[参数]),外部可以任意控制处理,这就是拦截器的基本原理。

 

3、控制反转和依赖注入

我们也可以用回调来实现,先简单理解下控制反转和依赖注入,首先依赖注入是控制反转的实现,

我们每次实例化对象的时候,都会现new一个新的对象,像var a = new b()

然后用a.xxx的方式来使用b中的属性和方法,但有一个地方调b的对象,要用到b里y1 : function(),另一个地方也调b对象,却不能有y1 : function(),

这样我们就不方便把控制权交给b对象,而是放在外面,而里面只需要让它自动new一个对象,这就是注入

简单来说就是外部只需要传入类的引用,外部就可以直接调用它的对象。

 1 export class SummaryComponent implements OnInit, AfterViewInit {
 2   constructor(public http: Http){
 3 
 4   ngOnInit() {
 5     //XHR异步请求:发送get请求
 6      this.http.get('./app/contact360/summary.sub.component.html').subscribe(data => {
 7         alert(data.text()); //如果请求的是文本:  data.text() ,  如果请求的是json文件:  data.json()
 8      });
 9   }
10 }

这是angular2注入的例子,在构造方法中传入Http这个类,正常我需要 this.http = new Http()

但现在我把new的控制权交给了angular,使它在实例化SummaryComponent的时候,顺便把构造方法中传入的类都实例化了,并反给自身,

这样,我们就可以不用new而直接可以调用this.http的对象,这么做也有个好处就是,new Http()的时候,我不知道传什么参数给它,而现在我也不用考虑这个了。

问:这和回调函数有什么关系?

答:都是把控制权交给外面,里面只做基本操作

 1 define(["demo"],function(_demo){ return new _demo(); }); 

知道模块化开发的同学都知道上面这个用于引入新外来模块用的,但如果define我这么写

1 _define = function(mods,func){
2     var _objs = [];
3     define(mods,function(){
4          for(var i=0;i<arguments.length;i++){
5              _objs.push(new arguments[i]);
6          }
7     });
8     func.apply(this,_objs);
9 }

用的时候我就不用new _demo()了,并可以直接用_demo.test()对象方法了

 1 _define(["demo"],function(_demo){ return _demo.test(); }); 

这就是通过回调函数来注入,

当然注入对象的主要还是通过调用接口和继承的方式,但原理依然脱离不了这种方式,

虽然原理很简单,但结合各种设计模式后,就会奥妙无穷。

转载于:https://www.cnblogs.com/wujianbufengsao/articles/9580413.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue 3中,可以使用JavaScript原生的定时器函数setInterval来创建计时器。引用中的代码示例展示了如何在Vue组件中创建一个每隔1秒钟更新一次的计时器。通过使用ref来创建一个响应式的计数器变量counter,并使用setInterval函数在每一秒钟更新一次counter的值。同时,需要在组件销毁之前使用onUnmounted钩子函数清除计时器,避免内存泄漏。 相比于原生JavaScript中使用setInterval函数,Vue 3中使用setInterval几乎是相同的。主要的区别在于Vue 3推荐的使用方式是通过Vue的生命周期钩子来创建和清除计时器。引用中的代码示例展示了在Vue组件中使用beforeDestroy钩子函数来清除计时器。这样做的好处是可以确保在组件销毁时正确地清除计时器,避免潜在的内存泄漏问题。 总的来说,Vue 3提供的计时器函数setInterval的使用方式与原生JavaScript中的setInterval几乎相同,都是用来创建定时器。主要区别在于Vue 3推荐使用Vue的生命周期钩子来创建和清除计时器,以确保在组件销毁时正确地清除计时器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue3中的定时器](https://blog.csdn.net/lyl87/article/details/130932314)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [听说你熟练使用Vue.js?这9种Vue技术你掌握了吗?](https://blog.csdn.net/duninet/article/details/108147164)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [vue 解决setTimeOut和setInterval函数无效报错的问题](https://download.csdn.net/download/weixin_38746387/12924615)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值