JavaScript基础CallBack函数(015)
前面提到,函数对象是可以作为参数传递给另一函数的,这时,作为参数的函数如果在内部被执行,那么它就是个回调函数(Callback):
- function writeCode(callback) {
- // do something...
- callback();
- // ...
- }
- function introduceBugs() {
- // ... make bugs
- }
- writeCode(introduceBugs);
在上面的代码里,introduceBugs就作为writeCode的参数,在writeCode函数的执行过程中被调用。因此introduceBugs就是一个回调(CallBack)函数。
下面给出一个更有实际意义的回调函数。假设我们有一个findNodes函数,它可以通过一个复杂的逻辑,在一个很大的数组中找到满足某个条件的所有结点,并返回这些结点:
- 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;
- };
一般来说我们都希望函数的功能单一化,所以这个函数只负责把满足某件的结点找到,并返回。然后我们写另外一个函数hide,可以把给定的一堆结点隐藏,这 个函数接受一个结点的数组作为参数,并把数组中的结点一个一个地隐藏。结合这两个函数,我们就可以完成一个组合功能,即找到一些结点,并把它们隐藏:
- 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());
看起来挺好。不过这种实现方法的执行效率并不高。这两个函数都需要进行一个很长的循环,则实际上,如果每找到一个满足就条件的结点,就立即把它隐藏,这样效率更高:因为只需要循环1次。为了实践这个想法,但依然把两个任务用不同的函数来实现,我们用回调的方式来做:
- // 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这时还是返回满足条件的所有结点,但它也接受一个回调函数,用于给每个满足条件的结点执行一些任务。这个任务就交给回调函数来声明。下面是具体的回调函数hide:
- // a callback function
- var hide = function (node) {
- node.style.display = "none";
- };
- // find the nodes and hide them as you go
- findNodes(hide);
当然,如果hide只服务于findNodes,有时我们不需要给它一个名字,从而把它声明为一个匿名的回调函数:
- // passing an anonymous callback
- findNodes(function (node) {
- node.style.display = "block";
- });
回调函数中的this
当回调函数中使用了this,比如,这个回调函数其实是对象myapp中的一个方法paint:
- var myapp = {};
- myapp.color = "green";
- myapp.paint = function (node) {
- node.style.color = this.color;
- };
这时我们有一个全局的函数findeNodes()接受一个回调函数:
- var findNodes = function (callback) {
- // ...
- if (typeof callback === "function") {
- callback(found);
- }
- // ...
- };
这时如果执行 findNodes(myapp.paint),并不能达到预期的结果。因为myapp.paint中的this指针在声明的时候指向的是对象中的属性, 也就是那个对象本身,但当myapp.paint作为回调函数在全局的函数findNodes时执行是,this指针在执行期间指向的就变成了全局的 this了(如果在浏览器中,就是dom对象)。
解决方法是把回调函数所属的对象也一并传递给findNodes,然后在执行回调函数时指定它所属的对象:
- findNodes(myapp.paint, myapp);
所以findNodes修改为这样:
- var findNodes = function (callback, callback_obj) {
- //...
- if (typeof callback === "function") {
- callback.call(callback_obj, found);
- }
- // ...
- };
这样看起来有点啰嗦,因为对象的名字在参数列表里出现了两次。我们也可以把这个回调函数的名字用字符串的方式传递:
- 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);
- }
- // ...
- };
JavaScript基础CallBack函数(015)的更多相关文章
- (Frontend Newbie)JavaScript基础之函数
函数可以说是任何一门编程语言的核心概念.要能熟练掌握JavaScript,对于函数及其相关概念的学习是非常重要的一步.本篇从函数的基本知识.执行环境与作用域.闭包.this关键字等方面简单介绍Java ...
- JavaScript基础学习-函数及作用域
函数和作用域是JavaScript的重要组成部分,我们在使用JavaScript编写程序的过程中经常要用到这两部分内容,作为初学者,我经常有困惑,借助写此博文来巩固下之前学习的内容. (一)JavaS ...
- JavaScript 基础回顾——函数
在JavaScript中,函数也是一种数据类型,属于 function 类型,所以使用Function关键字标识函数名.函数可以在大括号内编写代码并且被调用,作为其他函数的参数或者对象的属性值. 1. ...
- Javascript 基础--JS函数(三)
一.基本概念:未完成某一个功能的代码(语句,指令)的集合. 二.函数的调用方式: 2.1.函数名(传递参数1,传递参数2) 基本语法 function 函数名(参数列表){ //代码; retur ...
- javascript基础(五)函数
原文http://pij.robinqu.me/ 通过call和apply间接调用函数(改变this) call 和 apply带有多个参数,call和apply把当前函数的this指向第一个参数给定 ...
- javascript基础知识-函数
1.javascript中函数有两种定义方式: 函数语句定义和表达式定义 //函数有定义 function test(){ console.log("This is a function&q ...
- JavaScript基础——创建函数
JavaScript的最重要的一个部分是制作其他代码可以重用的代码.要做到这一点,你可以把代码组织成执行特定任务的函数.函数是结合在一个单一的块中,并给予一个名称的一系列代码语句.然后,你就可以通过引 ...
- JavaScript基础之函数与数组
函数 函数的基本概念 为完成某一功能的程序指令(语句)的集合,称为函数.有的程序员把函数称为方法,希望大家不要被这两个名词搞晕了. 函数分为:自定义函数.系统函数(经常查看js帮助手册). j ...
- javascript基础知识--函数定义
函数声明式 function funname( 参数 ){ ...执行的代码 } 声明式的函数并不会马上执行,需要我们调用才会执行:funname(); * 分号是用来分隔可执行JavaScript语 ...
随机推荐
- Java实现 LeetCode 541 反转字符串 II(暴力大法)
541. 反转字符串 II 给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转.如果剩余少于 k 个字符,则将剩余的所有全部反转.如果有小于 2k 但大于或 ...
- Java实现 LeetCode 173 二叉搜索树迭代器
173. 二叉搜索树迭代器 实现一个二叉搜索树迭代器.你将使用二叉搜索树的根节点初始化迭代器. 调用 next() 将返回二叉搜索树中的下一个最小的数. 示例: BSTIterator iterato ...
- Java实现 LeetCode 153 寻找旋转排序数组中的最小值
153. 寻找旋转排序数组中的最小值 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出其中 ...
- 第三届蓝桥杯JavaB组国(决)赛真题
解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.数量周期 [结果填空](满分9分) 复杂现象背后的推动力,可能是极其简单的原理.科学的目标之一就是发现纷繁复杂的自然现象背后的简单法则 ...
- java实现哈密顿回路问题
1 问题描述 什么是哈密顿回路? 引用自百度百科: 哈密顿图(哈密尔顿图)(英语:Hamiltonian path,或Traceable path)是一个无向图,由天文学家哈密顿提出,由指定的起点前往 ...
- OAuth2.0系列之基本概念和运作流程(一)
@ 目录 一.OAuth2.0是什么? 1.1 OAuth2.0简介 1.2 OAuth2.0官方文档 二.OAuth2.0原理 2.1 OAuth2.0流程图 三. OAuth2.0的角色 四.OA ...
- 「从零单排canal 02」canal集群版 + admin控制台 最新搭建姿势(基于1.1.4版本)
canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据 订阅 和 消费.应该是阿里云DTS(Data Transfer Service)的开 ...
- protobuf安装流程
protobuf安装流程 环境 平台 Ubuntu16.04 依赖 autoconf automake libtool curl make g++ 安装流程 在Ubuntu / Debian上,您 ...
- uni-app动态修改顶部导航栏标题
动态修改顶部导航栏标题有两种方法方式一.使用自定义到导航栏,覆盖原生导航栏 缺点:自定义到导航栏性能远远不如原生导航栏,手机顶部状态栏区域会被页面内容覆盖,这是因为窗体是沉浸式的原因,即全屏可写内容: ...
- DockerFile构建镜像和Docker仓库
利用commit理解镜像构成 注意: docker commit 命令除了学习之外,还有一些特殊的应用场合,比如被入侵后保存现 场等.但是,不要使用 docker commit 定制镜像,定制镜像应该 ...