Hello,今天和大家分享如何修改setInterval作用域。

0.引子

  最近在做一个项目的时候需要开发一个图片轮播显示的组件,在实现过程中遇到了关于setInterval作用域的问题。

  

 SlidePicture.prototype={
constructor:SlidePicture,
init:function(){ //初始化函数
this.autoPlay();
},
slidePic:function(){ //滑动图片具体实现
//省略实现代码
console.log('duration-->'+this.duration);
console.log('delay-->'+this.delay);
},
autoPlay:function(){ //自动轮播图片
setInterval(this.slidePic,this.delay);
}
}
//构造函数
function SlidePicture(delay,duration){
this.delay=delay;
this.duration=duration;
this.init();
} var sp=new SlidePicture(5000,800);

  在上面的代码中,我们自定义并扩展一个SlidePicture原型。主要总用就是,我们在创建原型对象时会调用window的setInterval方法,

  来定时调用图片切换方法,从而实现自动图片的自动轮播效果。

  slidePic方法中具体的实现方法我先省略了(下次可以继续和大家分享这个完整的组件),只是在这里打印了对象中的两个属性值,

  结果却出现以下信息:

  

  都是undefined,为什么呢?

  很明显问题不是出在SlidePicture对象上,因为我们已经给这个对象初始化过属性值了。

  打开firebug脚本调试,在第8行打上断点:

  

  终于发现了问题所在:slidePic方法中的this居然是指向window而不是当前的SlidePicture对象。

  

1.问题

  我们重新审查代码,结果把关注点提到第12行来:

setInterval(this.slidePic,this.delay);

  问题来了,setInterval以及setTimeout这些方法都是全局作用域window的函数,

  所以上面的代码等价于:

 setInterval(function(){
console.log('duration-->'+this.duration);
console.log('delay-->'+this.delay);
},this.delay);

  那么问题就清楚了,函数实现中的this当然是指向window了,千万别被this.slidePic蒙骗。

  既然this就是window,那么delay,duration这两个属性当然也就不存在了。

2.apply/call?

  既然是作用域的问题,那么解决问题的关键也就是如何修改setInterval的作用域了。

   修改函数作用域,我们的第一个方案当然就是apply/call了,我们按照理论尝试将代码修改如下:

autoPlay:function(){    //自动轮播图片
var self=this;
setInterval(self.slidePic.apply(self),this.delay);
}

  我们将当前对象this传递给apply方法,看起来应该是OK的,运行后结果如下:

  

  果然,结果出来了。

  等等,好像有点不对!这个结果只打印了一次,并不是根据setInterval定时循环调用的。

  换成了call结果也一样。

  查了查这两个方法:apply/call如果用在setInterval中的话,只会立即运行一次,而不会按照我们的设想循环调用。

  怎么办?

  我们的主角出场了:bind。

  call和apply是立即执行方法,而bind是产生一个新方法用于后续调用。

  我们修改了下代码:

setInterval(self.slidePic.bind(self),this.delay);

  果然我们想要的结果出现了:

  

  

3.匿名函数

  还有没有别的办法?

  其实在一开始的时候我们已经说了,给setInterval传递this.slidePic参数等价于:

1 setInterval(function(){
2 console.log('duration-->'+this.duration);
3 console.log('delay-->'+this.delay);
4 },this.delay);

  这里我们定义了一个匿名函数作为参数setInterval的第一个参数,但是忽略了一点,

  这个匿名函数中的this仍然指向window,所以这种做法当然也是不行。

  那么我们只要将this换成我们的SlidePicture对象就可以了。

  调整下代码:

autoPlay:function(){    //自动轮播图片
var self=this;
// setInterval(self.slidePic.bind(self),this.delay);
setInterval(function(){
self.slidePic();
},this.delay);
}

  在调用setInterval之前我们先将当前对象this保存下来,然后在匿名函数中调用了就OK了!

  这也是处理this对象的一种常见方案。

   ------写得乱七八糟的,不管怎样希望对各位有所帮助-----

  

修改setInterval作用域的更多相关文章

  1. javascript 欺骗词法作用域

    如果词法作用域完全由写代码期间函数所声明的位置来定义,怎样才能在运行时来"修改"(也可以说欺骗)词法作用域呢?    JavaScript 中有两种机制来实现这个目的.社区普遍认为 ...

  2. JavaScript夯实基础系列(一):词法作用域

      作用域是一组规则,规定了引擎如何通过标识符名称来查询一个变量.作用域模型有两种:词法作用域和动态作用域.词法作用域是在编写时就已经确定的:通过阅读包含变量定义的数行源码就能知道变量的作用域.Jav ...

  3. javasrcipt的作用域和闭包(二)

    这篇博客主要对词法作用域与欺骗词法作用域.函数作用域与块级作用域.函数内部的变量提成原理进行详细的分析,在这篇博客之前,关于作用域.编译原理.浏览器引擎的原理及关系在javaScript的作用域和闭包 ...

  4. AngularJs之Scope作用域

    前言: 上篇博文AngularJs之directive中说了Scope作用域是个大坑,所以拿出来作为重点总结! 什么是scope AngularJS 中,作用域是一个指向应用模型的对象,它是表达式的执 ...

  5. JavaScript:修改作用域外变量

    今天在看JavaScript学习指南的时候做的课后习题,也因此详细的对函数的传入参数进行比较深入的研究. 题目如下: 函数如何才能修改其作用域之外的变量?编写一个函数,由1~5的数字组成的数组作为参数 ...

  6. JS中setInterval、setTimeout不能传递带参数的函数的解决方案

    在JS中无论是setTimeout还是setInterval,在使用函数名作为调用句柄时都不能带参数,而在许多场合必须要带参数,接下来为大家介绍具体的解决方法 在JS中无论是setTimeout还是s ...

  7. 《你不知道的JavaScript》第一部分:作用域和闭包

    第1章 作用域是什么 抛出问题:程序中的变量存储在哪里?程序需要时,如何找到它们? 设计 作用域 的目的:为了更好地存储和访问变量. 作用域:根据名称查找变量的一套规则,用于确定在何处以及如何查找变量 ...

  8. 理解AngularJS的作用域Scope

    AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法.但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独 ...

  9. phpcms后台部分修改

    1.后台登陆前提示信息取消及成功后提示信息取消.    (1)后台登陆前提示信息取消               phpcms\modules\admin\classes\admin.class.ph ...

随机推荐

  1. Python win7下 django-admin.py startproject mysite命令没有创建mysite?

    解决方案 解决:这个命令在XP下正常(我没试过),我用的win7,无法创建.这属于django的一个bug. 方法是:修改注册表中 HKEY_CLASSES_ROOT/Applications/pyt ...

  2. ZJOI Day 2 游记

    ---恢复内容开始--- 去ZJOI Day 2打了一会酱油...各种神犇大爷都来屠,南外的小朋友也来屠我们了真是感动...没有看到毛爷爷真是可惜.. Day[-1] 早上还在上课,吃完中饭立马跑去找 ...

  3. 【OpenStack】OpenStack系列17之OpenStack私有云设计一

    [软件系统] 1.操作系统(Minimal最小化安装): CentOS-6.6-x86_64,CentOS 6最后一个版本,官方建议版本. 相对于6.5版本: 强化对 SCSI 设备的处理,有助应付某 ...

  4. String是引用类型

    关于String为值类型还是引用类型的讨论一直没有平息,最近一直在研究性能方面的问题,今天再次将此问题进行一次明确.希望能给大家带来点帮助. 如果有错误请指出. 来看下面例子: //值类型 ; int ...

  5. 90天打造日均在线网站1W+的友情链接平台

    导读:三个月过去了,好友张森终于把一款默默无名的软件打造出了日均1W+在线的平台,我认为成功的因素很简单,1,找准了用户群体的痛点;2,肯花精力做运营;3,合理的推广.本文是他的自述,打造一款产品,说 ...

  6. WebSite和WebApplication的区别

    1. WebApplication(Web应用程序)和WebSite(网站)的区别:WebSite是为了兼容从ASP转过来的开发人员的习惯而存在的,用起来简单,例如:不需要创建命名控件.C#代码修改以 ...

  7. DFS:Curling 2.0(POJ 3009)

      冰壶2.0 题目大意:就是给你一个冰壶和一个地图,地图上有石头,冰壶只能沿着x方向和y方向运动,并且要一直运动直到撞到石头为止,并且沿着此方向撞过来会把挡住的石头撞没,冰壶在停的时候可以扔出去一次 ...

  8. mongoose学习笔记1--基础知识2

    Schema简述 Schema —— 一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力,仅仅只是数据库模型在程序片段中的一种表现,可以说是数据属性模型(传统 ...

  9. vi 命令 用法(转)

    一.Unix编辑器概述       编辑器是使用计算机的重要工具之一,在各种操作系统中,编辑器都是必不可少的部件.Unix及其相似的ix 操作系统系列中,为方便各种用户在各个不同的环境中使用,提供了一 ...

  10. hdu 5115 区间dp ***

    题意:有n只狼,每只狼有两种属性,一种攻击力一种附加值,我们没杀一只狼,那么我们受到的伤害值为这只狼的攻击值与它旁边的两只狼的附加值的和,求把所有狼都杀光受到的最小的伤害值. 枚举中间k作为最后杀死的 ...