JavaScript回调函数
最近在自学cocos游戏开发,学习到触摸事件监听时,对回调函数的内容不太理解。
cc.node.on
在节点上注册指定类型的回调函数,也可以设置 target 用于绑定响应函数的 this 对象。
通过搜集资料,大概有了一定的认识,总结一下。
什么是回调函数?
- 百度百科的解释:
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 - 其他一些博客的解释:
一个回调函数,也被称为高阶函数,是一个被作为参数传递给另一个函数(在这里我们把另一个函数叫做“otherFunction”)的函数,回调函数在otherFunction中被调用。一个回调函数本质上是一种编程模式(为一个常见问题创建的解决方案),因此,使用回调函数也叫做回调模式。
简而言之,回调函数可理解为C语言中的函数指针,可作为参数传递给其他函数进行调用。正是由于函数指针的灵活性,使用回调函数可以起到精简代码、提高代码重用性的作用。
什么叫“注册”回调函数?
首先我们来看看回调函数的运行机制:
1、定义一个回调函数
2、提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
3、当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
由这段文字我们可以看到:
注册——将回调函数作为参数传入调用者
调用——使用函数指针对该函数进行调用
回调函数的使用方法
理解了概念和基本原理,使用起来就很简单啦。
我们可以直接通过函数指针传递函数的定义:
//定义函数
on_touch_move : function(t) {
var offset = t.getDelta();
this.node.x += offset.x;
this.node.y += offset.y;
};
//this.node.on()函数用函数指针注册on_touch_move()回调函数
this.node.on(cc.Node.EventType.TOUCH_MOVE , on_touch_move ,this);
也可以通过匿名函数,直接传入函数的定义体,来传递回调函数:
//cocos-触摸移动事件
this.node.on(cc.Node.EventType.TOUCH_MOVE,function(t){
var offset = t.getDelta();
this.node.x += offset.x;
this.node.y += offset.y;
},this);
回调函数的作用域范围
由于回调函数是作为指针被传入其他函数中的,因此,回调函数所能操作的变量(能通过回调函数控制的变量)需要明确一下。
当我们将一个回调函数作为变量传递给另一个函数时,这个回调函数在包含它的函数内的某一点执行,就好像这个回调函数是在调用者函数中定义的一样。这意味着回调函数本质上是一个闭包。
正如我们所知,闭包能够进入包含它的函数的作用域,因此回调函数能获取包含它的函数中的变量,以及全局作用域中的变量。
回调函数的this绑定
在cocos使用cc.node.on时,常常会看到参数列表中,回调函数的后面加了“.bind(this)”,这个是JavaScript中this绑定的问题,这里简要介绍一下。
JavaScript的this绑定默认的是动态绑定,即根据脚本执行位置处的this来动态的确定所绑定的对象,如果不加显示绑定的话,可能会在执行过程中出现绑定对象丢失的情况。
显示绑定的方法主要有call()、apply()和bind()
- call() 的基本使用方式: fn.call(object)
fn是我们调用的函数,object参数是我们希望函数的this所绑定的对象。
fn.call(object)的作用:
1、即刻调用这个函数(fn)
2、调用这个函数的时候函数的this指向object对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ufiMroku-1593239991671)(https://s2.ax1x.com/2019/04/25/Ee086x.jpg)] - bind() 的基本使用方式: fn.bind(object)
使用方法和call()基本相同。bind和call的区别是,call将立即执行该函数,bind不执行函数,只返回一个可供执行的函数 。
用 cc.node.on 监听触摸事件的使用实例
不使用对象绑定:
cc.Class({
extends: cc.Component,
properties: {
},
on_touch_start: function(t){
console.log("[info]:cc.Node.EventType.TOUCH_START called");
console.log("[info]:start pos:",t.getLocation().x,t.getLocation().y);
},
onLoad: function () {
this.node.on('touchstart', on_touch_start),
});
事件监听函数 on 可以传第三个参数 target,用于绑定响应函数的调用者。以下两种调用方式, 效果上是相同的:
cc.Class({
extends: cc.Component,
properties: {
},
on_touch_start: function(t){
console.log("[info]:cc.Node.EventType.TOUCH_START called");
console.log("[info]:start pos:",t.getLocation().x,t.getLocation().y);
},
onLoad(){
// 使用函数绑定
this.node.on('on_touch_start', function ( event ) {
this.enabled = false;
}.bind(this));
// 使用第三个参数
this.node.on('on_touch_start', function (event) {
this.enabled = false;
}, this);
},
});