当前位置: 首页 > 编程日记 > 正文

javascript回调函数笔记

来源于:https://github.com/useaname/blog-study

在Javascript中,函数是第一类对象。意味函数可以像对象一样按照第一类被管理使用。
回调函数是从一个叫函数式编程的编程范式中衍生出来的概念。简单来说,函数式编程就是使用函数作为变量。函数式编程过去 - 甚至是现在,依旧没有被广泛使用 - 它过去常被看做是那些受过特许训练的,大师级别的程序员的秘传技巧。

# 什么是回调或者高阶函数
一个回调函数,也被称为高阶函数,是一个被作为参数传递给另一个函数(在这里我们把另一个函数叫做“otherFunction”)的函数,回调函数在otherFunction中被调用。一个回调函数本质上是一种编程模式(为一个常见问题创建的解决方案),因此,使用回调函数也叫做回调模式。

jQuery中的回调函数:
```javascript
$("#btn").click(function(){
alert("btn is clicked");
});
```
正如你在前面的例子中看到的,我们将一个函数作为参数传递给了click方法。click方法会调用(或者执行)我们传递给它的函数。这是Javascript中回调函数的典型用法,它在jQuery中广泛被使用。
```javascript
var friends = ["mike", "stacy", "Andy", "Rick"];
friends.foreach(function(o,i){
console.log(index + 1 + ": " + o);
});
```
回调函数既闭包:
将一个回调函数作为变量传递给另一个函数时,这个回调函数在包含它的函数内的某一点执行。就好像这个回掉函数是在包含它的函数中定义一样。意味着回调函数本质上是一个闭包。
闭包能够进入包含它的作用域,因此回调函数能获取包含它的函数中的变量,以及全局作用域中的变量。
# 实现回调函数的基本原理
### 使用命名或匿名函数作为回调
在前面的例子中,使用了在参数位置定义的匿名函数作为回调函数。这是在回调函数中普遍使用的魔术。另一种常见的是顶一个命名函数并将函数名作为变量传递给函数。比如:
```javascript
//全局变量
var allUserData = [];
//普通函数
function logStuff(userData){
if( typeof userData === "string"){
console.log(userData);
}else if( typeof userData === "object"){
for(var item in userData){
console.log(item + ": " + userData[itme]);
}
}
}
```
//一个函数接收两个参数,后一个参数为回调函数
```javascript
function getInput(options, callback){
allUserData.push(options);
callback(options);
}

//调用getInput时,将logStuff传递给他
//因此logStuff将会在getInput内被回调(执行)
getInput({name:"Rich",speciality:"Javascript"},logStuff);
//name:Rick
//speciality:Javascript
```

# 允许多重回调函数

```javascript
将不止一个的回调函数作为参数传递给一个函数,就像我们能够传递不止一个变量一样。这里有一个关于jQuery中AJAX的例子:
function successCallback(){
//在发送之前做点什么
}

function successCallback(){
//在信息被成功接收之后做点什么
}

function completeCallback(){
//在完成之后做点什么
}

function errorCallback(){
//当错误发生时做点什么
}

$.ajax({
url:"http://fiddle.jshell.net/favicon.png",
success:successCallback,
complete:completeCallback,
error:errorCallback

});
```

# 创建自己的回调函数
使用回调函数是如此的简单而强大,你应该查看你的代码看看有没有能使用回调函数的地方。回调函数将在以下几个方面帮助你:

* 避免重复代码(DRY-不要重复你自己) - 在你拥有更多多功能函数的地方实现更好的抽象(依然能保持所有功能) - 让代码具有更好的可维护性
* 使代码更容易阅读
* 编写更多特定功能的函数

下面的函数将完成:读取用户信息,用数据创建一首通用的诗,并且欢迎用户。这个本来是个非常复杂的函数因为它包含很多if/else语句,且将在调用那些用户数据需要的功能方面有诸多不兼容性。

getUserInput函数是多功能的:它能执行具有多种功能的回调函数。

```javascript
//首先,创建通用诗的生成函数;它将作为下面的getUserInput函数的回调函数
function genericPoemMaker(name, gender){
console.log(name + " is finer than fine wine.");
console.log("Altruistic and noble for the modern time.");
console.log("Always admirably adorned with the latest style.");
console.log("A " + gender + " of unfortunate tragedies who still manages a perpetual smile");
}
//callback,参数的最后一项,将会是我们在上面定义的genericPoemMaker函数
function getUserInput(firstName, lastName, gender, callback) {
var fullName = firstName + " " + lastName;
// Make sure the callback is a function
if(typeof callback === "function"){
// Execute the callback function and pass the parameters to it
callback(fullName, gender);
}
}

//调用getUserInput函数并将genericPoemMaker函数作为回调函数:
getUserInput("Michael", "Fassbender", "Man",genericPoemMaker);
```
因为getUserInput函数仅仅只负责提取数据,我们可以把任意回调函数传递给它。例如,我们可以传递一个greetUser函数:

```javascript
function greetUser(customerName, sex) {
var salutation = sex && sex === "Man" ? "Mr." : "Ms.";
console.log("Hello, " + salutation + " " + customerName);
}

// 将greetUser作为一个回调函数
getUserInput("Bill", "Gates", "Man", greetUser);

// 这里是输出
Hello, Mr. Bill Gate
```
调用了完全相同的getUserInput函数,但是这次完成了一个完全不同的任务。

相关文章:

工厂方法模式与抽象工厂模式的区别

工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。 抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具…

LSGO代码小组第18周复盘日志

LSGO软件技术团队第18周代码小组学习复盘日志。

唐山松下焊接机器人编程招聘_机器人四小家族-松下Panasonic专注焊接

在日本松下的网站,机器人是和焊接系统方案是在一起的。松下机器人的历史(来源于松下公司网站)1980年松下AW系列弧焊机器人投放上市,机器人系统之间采用的是单向模拟通讯方式模拟通讯的机器人1983年示教的容易化1988年减少干涉的设…

基于Matlab的BP神经网络在非线性函数拟合中的应用

本图文详细介绍了如何利用Matlab神经网络工具箱实现BP神经网络对非线性函数的拟合。

aligned_storage简单学习

#include <iostream> #include <type_traits> #include <string>/* template< std::size_t Len, std::size_t Align default-alignment >struct::type aligned_storage; 相当于一个内建的POD类型他的大小是Size他的对齐方式是Align */ template<c…

有关高级关系引擎中存在错误

SQL server2005 Analysis Services项目中出现以下错误 高级关系引擎中存在错误。 无法与 DataSourceID 为“Adventure Works DW”、名称为“Adventure Works DW”的数据源建立连接。 但是数据源测试连接是好使的&#xff0c;搜到已解决办法&#xff0c;数据源对里双击&#xf…

c#中接口的使用方法图解_C#图解教程 第十五章 接口

接口什么是接口接口是指定一组函数成员而不实现它们的引用类型。所以只能类和结构来实现接口。这种描述比较抽象&#xff0c;直接来看个示例。下例中&#xff0c;Main方法创建并初始化了一个CA类的对象&#xff0c;并将该对象传递给PrintInfo方法。classCA{public stringName;p…

提高C#编程水平的50个要点

1.总是用属性 (Property) 来代替可访问的数据成员 2.在 readonly 和 const 之间&#xff0c;优先使用 readonly 3.在 as 和 强制类型转换之间&#xff0c;优先使用 as 操作符 4.使用条件属性 (Conditional Attributes) 来代替条件编译语句 #if 5.总是为自定义类重载 ToString 方…

1.6 INSERT语句

1.6 INSERT语句正在更新内容&#xff0c;请稍后

基于Matlab的多层BP神经网络在非线性函数拟合中的应用

本图文详细介绍了如何利用Matlab神经网络工具箱实现多层BP神经网络对非线性函数的拟合。

华为云大数据存储的冗余方式是三副本_大数据入门:HDFS数据副本存放策略

大数据处理当中&#xff0c;数据储存始终是一个重要的环节&#xff0c;从现阶段的市场现状来说&#xff0c;以Hadoop为首的大数据技术框架&#xff0c;仍然占据主流地位&#xff0c;而Hadoop的HDFS&#xff0c;在数据存储方面&#xff0c;仍然得到重用。今天的大数据入门分享&a…

linux调试C++错误: 程序中有游离的‘\240’‘\302’

今天在网上找到一个小程序&#xff0c;一编译出现一大堆的错误&#xff1a; 程序中有游离的 ......开始觉得可能我从网页上直接复制的代码中有别的字符。于是把中文的全角空格全部替换了。这次好多了&#xff0c;少了一些&#xff0c;不过还有很多&#xff0c;调试信息说是XX行…

IE8下不识别indexOf的问题

1、为Array原型添加indexOf方法(如果学过面向对象,相当于给Array类添加实例方法),方法体如下: //添加数组IndexOf方法 if (!Array.prototype.indexOf){Array.prototype.indexOf function(elt /*, from*/){var len this.length >>> 0;var from Number(arguments[1])…

《C#精彩实例教程》小组阅读05 -- C#变量与常量

本微信图文介绍了C#的变量与常量。

k均值聚类算法考试例题_一文读懂K-means聚类算法

1、引言什么是聚类&#xff1f;我们通常说&#xff0c;机器学习任务可以分为两类&#xff0c;一类是监督学习&#xff0c;一类是无监督学习。监督学习&#xff1a;训练集有明确标签&#xff0c;监督学习就是寻找问题&#xff08;又称输入、特征、自变量&#xff09;与标签&…

《C#精彩实例教程》小组阅读06 -- C#运算符与表达式

本微信图文介绍了C#的运算符与表达式。

kvm启动报错

[rootstorage ~]# virsh -c qemu:///system list error: failed to connect to the hypervisor error: Failed to connect socket to /var/run/libvirt/libvirt-sock: No such file or directory原因&#xff1a;libvirt未启动解决方法[rootstorage ~]# libvirtd -d [rootst…

邀请参加活动的邀请函_圣诞节活动策划邀请函在线制作

2020年就要过去了&#xff0c;许多人说这一年很难&#xff0c;难上加南。莎士比亚说凡是过去&#xff0c;皆为序章。无论好的还是坏的终究会成为过往&#xff0c;向前看吧。圣诞节快要到来&#xff0c;商场开始布置精致的橱窗&#xff0c;电商巨头也在忙着做促销&#xff0c;幼…

比较全的字符串验证类,有人顶的话以后继续发

啥也不说看代码哈~ Codeusing System;using System.Collections.Generic;using System.Text;using System.Text.RegularExpressions;namespace Utility { public class ISExt { private static ISExt instance null; public static ISExt GetInstance…

设计模式(2)工厂方法模式(Factory Method)

设计模式&#xff08;0&#xff09;简单工厂模式 设计模式&#xff08;1&#xff09;单例模式&#xff08;Singleton&#xff09; 源码地址 0 工厂方法模式简介 0.0 工厂方法模式定义 工厂方法模式是在简单工厂模式基础上&#xff0c;为解决更复杂的对象创建问题而衍生进化出来…

基于Matlab的遗传算法优化BP神经网络在非线性函数拟合中的应用

本微信图文详细介绍了遗传算法优化BP神经网络初始权值阈值的过程&#xff0c;并通过实例说明该优化能够提升BP神经网络的预测精确程度。

android 加载h5页面部分机型滑动卡顿回弹_网易爆款H5 的交互方法参考

在早些年&#xff0c;H5其实更像是手机上的PPT&#xff0c;只支持点击、滑动这些基础手势操作。以内容展示为主&#xff0c;交互形式为辅。但到了今天&#xff0c;H5的玩法已经有了质的突破。不仅交互形式超多&#xff0c;形式与内容也能紧密结合&#xff0c;产生11大于2的效果…

使用SDL打造游戏世界之入门篇 - 1

来源&#xff1a;天极开发 作者&#xff1a;维维编译 出处&#xff1a;巧巧读书 2007-07-17 进入讨论组 简介 Simple DirectMedia Layer, 简称SDL&#xff0c;是一个自由的跨平台的多媒体开 发包&#xff0c;主要通过OpenGL和2D视频帧缓冲(framebuffer)提供对音频、键盘、鼠标…

RBAC新解 - 基于资源的权限管理

1、什么是角色 当说到程序的权限管理时&#xff0c;人们往往想到角色这一概念。角色是代表一系列可执行的操作或责任的实体&#xff0c;用于限定你在软件系统中能做什么、不能做什么。用户帐号往往与角色相关联&#xff0c;因此&#xff0c;一个用户在软件系统中能做什么取决于…

《C#精彩实例教程》小组阅读07 -- C#字符与字符串

本微信图文详细介绍了C#中的字符与字符串。

syslog打印不带等级_printk的日志级别和控制台级别

printk根据日志级别(loglevel)对消息进行分类。日志级别用宏定义&#xff0c;日志级别宏展开为一个字符串&#xff0c;在编译时由预处理器将它和消息文本拼接成一个字符串&#xff0c;因此printk 函数中日志级别宏和格式字符串间不能有逗号。下面是两个printk的例子&#xff0c…

《C#精彩实例教程》小组阅读08 -- C#流程控制语句

本微信图文详细介绍了C#的流程控制语句。

ASPJPEG缩略图生成函数

好久没有发文章&#xff0c;贴一段代码出来晒晒&#xff01;一段aspjpeg组件生成缩略图的代码&#xff0c;有4种生成方式&#xff0c;建议用最后一种&#xff0c;生成的缩略图最清晰而且不会拉伸、变形&#xff01;做图片生成最好不过&#xff01;// 缩略图生成函数 Code By S…

java面试题收集

2019独角兽企业重金招聘Python工程师标准>>> 1.什么是B/S架构&#xff1f;什么是C/S架构 B/S(Browser/Server)&#xff0c;浏览器/服务器程序 C/S(Client/Server)&#xff0c;客户端/服务端&#xff0c;桌面应用程序 2.你所知道网络协议有那些&#xff1f; HTTP&…

mobile还有人用吗 spring_话说,苹果手机语音备忘录功能还有人用吗?

hi&#xff0c;各位&#xff0c;苹果手机自带的语音备忘录功能还有人在用吗&#xff1f;前两天&#xff0c;有小伙伴在后台留言问&#xff1a;“苹果手机语音备忘录怎么恢复&#xff1f;”小编一时还有些恍惚“它是什么&#xff0c;手机上有吗&#xff1f;”&#xff0c;好在通…