JavaScript:回调模式(Callback Pattern)
函数就是对象,所以他们可以作为一个参数传递给其它函数;
当你将introduceBugs()作为一个参数传递给writeCode(),然后在某个时间点,writeCode()有可能执行(调用)introduceBugs();
这种情况下,introduceBugs()被称为回调函数(callback function)或简称为回调(callback:):
- function writeCode(callback) {
- // do something...
- callback();
- // ...
- }
- function introduceBugs() {
- // ... make bugs
- }
- writeCode(introduceBugs);
function writeCode(callback) {
// do something...
callback();
// ...
}
function introduceBugs() {
// ... make bugs
}
writeCode(introduceBugs);
注意introduceBugs()作为一参数传递给writeCode()是没有使用括号的;
使用括号会立即执行函数,然而在这种情况下,我们希望的是只传递一个指向函数的引用,让writeCode()在适当的时候去执行;
一个回调的例子(A Callback Example)
- var findNodes = function() {
- var i = 100000,
- // big, heavy loop
- nodes = [],
- // stores the result
- found; // the next node found
- while (i) {
- i -= 1;
- // complex logic here...
- nodes.push(found);
- }
- return nodes;
- };
var findNodes = function() {
var i = 100000,
// big, heavy loop
nodes = [],
// stores the result
found; // the next node found
while (i) {
i -= 1;
// complex logic here...
nodes.push(found);
}
return nodes;
};
将这个函数保持通用性并让它返回一个DOM节点(node)的数组是个好主意,但没有对实际的元素做任何事情;
- var hide = function(nodes) {
- var i = 0,
- max = nodes.length;
- for (; i < max; i += 1) {
- nodes[i].style.display = "none";
- }
- };
- // executing the functions
- hide(findNodes());
var hide = function(nodes) {
var i = 0,
max = nodes.length;
for (; i < max; i += 1) {
nodes[i].style.display = "none";
}
};
// executing the functions
hide(findNodes());
这种实现是没有效率的,因为hide()不得不再遍历一次findNodes()返回的的数组;
- // refactored findNodes() to accept a callback
- var findNodes = function(callback) {
- var i = 100000,
- nodes = [],
- found;
- // check if callback is callable
- if (typeof callback !== "function") {
- callback = false;
- }
- while (i) {
- i -= 1;
- // complex logic here...
- // now callback:
- if (callback) {
- callback(found);
- }
- nodes.push(found);
- }
- return nodes;
- };
// refactored findNodes() to accept a callback
var findNodes = function(callback) {
var i = 100000,
nodes = [],
found;
// check if callback is callable
if (typeof callback !== "function") {
callback = false;
}
while (i) {
i -= 1;
// complex logic here...
// now callback:
if (callback) {
callback(found);
}
nodes.push(found);
}
return nodes;
};
这样的实现是简单明确的,唯一增加的工作就是findNodes()检查了可选的回调函数是否有被提供,如果有,就执行它;
- // a callback function
- var hide = function(node) {
- node.style.display = "none";
- };
- // find the nodes and hide them as you go
- findNodes(hide);
// a callback function
var hide = function(node) {
node.style.display = "none";
};
// find the nodes and hide them as you go
findNodes(hide);
回调函数可以是一个在代码中已经存在的函数,也可以是一个匿名函数(当你调用主函数的时候才会创建);
- // passing an anonymous callback
- findNodes(function (node) {
- node.style.display = "block";
- });
// passing an anonymous callback
findNodes(function (node) {
node.style.display = "block";
});
回调和作用域(Callbacks and Scope)
在前面这个例子中,回调函数执行的部分可能像:
- callback(parameters);
callback(parameters);
虽然这样很简单并且在很多情况下都已经足够了;
- var myapp = {};
- myapp.color = "green";
- myapp.paint = function(node) {
- node.style.color = this.color;
- };
var myapp = {};
myapp.color = "green";
myapp.paint = function(node) {
node.style.color = this.color;
};
findNodes()函数做了类似下面的事:
- var findNodes = function(callback) {
- // ...
- if (typeof callback === "function") {
- callback(found);
- }
- // ...
- };
var findNodes = function(callback) {
// ...
if (typeof callback === "function") {
callback(found);
}
// ...
};
如果你调用了findNodes(myapp.paint),它并不能按照预期的那样工作,因为this.color将会是undefined;
- findNodes(myapp.paint, myapp);
findNodes(myapp.paint, myapp);
紧跟着,我们需要去修改findNodes()去绑定(bind)传递进来的对象:
- var findNodes = function(callback, callback_obj) {
- //...
- if (typeof callback === "function") {
- callback.call(callback_obj, found);
- }
- // ...
- };
var findNodes = function(callback, callback_obj) {
//...
if (typeof callback === "function") {
callback.call(callback_obj, found);
}
// ...
};
- findNodes(myapp.paint, myapp);
findNodes(myapp.paint, myapp);
会变成:
- findNodes("paint", myapp);
findNodes("paint", myapp);
那么findNodes()可能会做一些事,就像下面几行:
- var findNodes = function(callback, callback_obj) {
- if (typeof callback === "string") {
- callback = callback_obj[callback];
- }
- //...
- if (typeof callback === "function") {
- callback.call(callback_obj, found);
- }
- // ...
- };
var findNodes = function(callback, callback_obj) {
if (typeof callback === "string") {
callback = callback_obj[callback];
}
//...
if (typeof callback === "function") {
callback.call(callback_obj, found);
}
// ...
};
匿名的事件监听器(Asynchronous Event Listeners)
回调模式在日常中被经常使用,比如,当你附加一个事件监听器给页面上的某个元素时,你实际上提供了一个指向了回调函数的引用,并且在事件发生时被调用;
- document.addEventListener("click", console.log, false);
document.addEventListener("click", console.log, false);
绝大部分客户端浏览器都是事件驱动的(event-driven);
Timeouts
- var thePlotThickens = function () {
- console.log('500ms later...');
- };
- setTimeout(thePlotThickens, 500);
var thePlotThickens = function () {
console.log('500ms later...');
};
setTimeout(thePlotThickens, 500);
再次注意一下,thePlotThickens是如何被作为一个参数传递的,没有使用括号;
类库中的回调(Callbacks in Libraries)
JavaScript:回调模式(Callback Pattern)的更多相关文章
- JavaScript:回调模式(Callback Pattern) (转载)
JavaScript:回调模式(Callback Pattern) 函数就是对象,所以他们可以作为一个参数传递给其它函数: 当你将introduceBugs()作为一个参数传递给writeCode() ...
- JavaScript学习笔记(十二) 回调模式(Callback Pattern)
函数就是对象,所以他们可以作为一个参数传递给其它函数: 当你将introduceBugs()作为一个参数传递给writeCode(),然后在某个时间点,writeCode()有可能执行(调用)intr ...
- js作为参数,并且返回值;js的回调模式 callback
有这样一个情景,当我们弹出一个 prompt的时候,要求用户在文本框输入一个文字,然后点击确认,就可以拿到返回值 var temp=prompt("请输入您的名字"); a ...
- React Render Callback Pattern(渲染回调模式)
React Render Callback Pattern,渲染回调模式,其实是将this.props.children当做函数来调用. 例如: 要根据user参数确定渲染Loading还是Profi ...
- 理解javascript中的回调函数(callback)【转】
在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...
- 理解javascript中的回调函数(callback)
以下内容来源于:http://www.jb51.net/article/54641.htm 最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs ...
- JavaScript系列之回调函数callback
JavaScript系列之回调函数callback JavaScript回调函数的使用是很常见的,引用官方回调函数的定义: A callback is a function that is passe ...
- 理解 JavaScript 回调函数并使用
JavaScript中,函数是一等(first-class)对象:也就是说,函数是 Object 类型并且可以像其他一等对象(String,Array,Number等)一样使用.它们可以"保 ...
- javascript运行模式:并发模型 与Event Loop
看了阮一峰老师的JavaScript 运行机制详解:再谈Event Loop和[朴灵评注]的文章,查阅网上相关资料,把自己对javascript运行模式和EVENT loop的理解整理下,不一定对,日 ...
随机推荐
- springcloud使用Zuul构建微服务网关入门
为什么要使用微服务网关 不同的微服务一般会经过不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求. 如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会多次请求不同的微 ...
- 大数据的常用算法(分类、回归分析、聚类、关联规则、神经网络方法、web数据挖掘)
在大数据时代,数据挖掘是最关键的工作.大数据的挖掘是从海量.不完全的.有噪声的.模糊的.随机的大型数据库中发现隐含在其中有价值的.潜在有用的信息和知识的过程,也是一种决策支持过程.其主要基于人工智能, ...
- 001_docker-compose构建elk环境
由于打算给同事分享elk相关的东西,搭建配置elk环境太麻烦了,于是想到了docker.docker官方提供了docker-compose编排工具,elk集群一键就可以搞定,真是兴奋.好了下面咱们开始 ...
- apache+php windows下配置
2014年1月9日 13:58:54 现在PHP大部分是vc9编译的,其扩展在windows下大部分也都是用vc9编译的(memcache,xdebuge...),,所以要想Apache+PHP+PH ...
- JavaScript深入解读
JavaScript是运行在浏览器上的脚本语言.我们平时看到丰富多彩的网页,这要在很大程度上归功于JavaScript. 引子 学点儿历史 JavaScript在编程语言的阵营里也是老资格了.它诞生于 ...
- JavaEE之JavaWeb简介
- 和为k的最长子数组及其延伸
问题1: /** * 问题描述: * 给定一个无序数组arr,其中元素可正.可负.可0, * 求arr所有的子数组中正数与负数个数相等的最长子数组长度 * * 解题思路:对数组进行处理,正数为1,负数 ...
- hdu 1700 (圆的内接三角形 要周长最大)
以原点为圆心,给出圆上的一点,要求圆上的另外两点,使得这三个点的距离和最大,很容易想到这是一个等边三角形然后有这两个公式 点a为已知点a*b=|a|*|b|*cos(120); x*x+y*y=r*r ...
- Codeforces 466E Information Graph
Information Graph 把询问离线之后就能随便搞了, 去check一下是不是祖先, 可以用倍增也能用dfs序. #include<bits/stdc++.h> #define ...
- python scrapy 调试模式
scrapy通过命令行创建工程,通过命令行启动爬虫,那么有没有方式可以在IDE中调试我们的爬虫呢? 实际上,scrapy是提供给我们工具的, 1. 首先在工程目录下新建一个脚本文件,作为我们执行爬虫的 ...