迭代器(iterator)是一个可以顺序存取数据集合的对象。其一个典型的API是next方法。该方法获得序列中的下一个值。

迭代器示例

题目:希望编写一个便利的函数,它可以接收任意数量的参数,并为这些值建立一个迭代器。

测试代码好下:

var it=values(1,4,1,4,2,1,3,5,6);
it.next();//1
it.next();//4
it.next();//1
分析:由于values函数需要接收任意多个参数,这里就需要用到上一节讲到的构建可变参数的函数的方法。然后里面的迭代器对象来遍历arguments对象的元素。

初步编码

function values(){
var i=0,n=arguments.length;
return {
hasNext:function(){
return i<n;
},
next:function(){
if(this.hasNext()){
return arguments[i++];
}
throw new Error("已经到达最后啦");
}
}
}

用上面的测试代码进行测试

var it=values(1,4,1,4,2,1,3,5,6);
it.next();//undefined
it.next();//undefined
it.next();//undefined

错误分析

代码运行结果并不正确,下面就对初始的编码程序进行分析。

function values(){
var i=0,n=arguments.length;//这里没有错误,arguments是values里的内置对象
return {
hasNext:function(){
return i<n;
},
next:function(){
if(this.hasNext()){
return arguments[i++];//错误出现在这里,arguments是next方法函数的内置对象。
}
throw new Error("已经到达最后啦");
}
}
}

这里的指代错误,很像是另一个让人头痛的对象this。处理this的指向时,通常是使用变量和保存正确的this。然后在其它地方使用这个变量。那么arguments对象的解决方案就出来了,借助一个变量来存储,这样arguments对象的指代就没有问题了。

再次编码

function values(){
var i=0,n=arguments.length,arg=arguments;
return {
hasNext:function(){
return i<n;
},
next:function(){
if(this.hasNext()){
return arg[i++];
}
throw new Error("已经到达最后啦");
}
}
}

运行测试代码

var it=values(1,4,1,4,2,1,3,5,6);
it.next();//1
it.next();//4
it.next();//1

结果和预期的相同。

提示

  • 当引用arguments时当心函数嵌套层级

  • 绑定一个明确作用域的引用到arguments变量,从而可以在嵌套的函数中引用它

附录一:迭代器

迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器上遍历的接口,设计人员无需关心容器的内容。

迭代器UML类图

迭代器js实现

对设计模式了解一点点,但具体项目中,有得多的也就是工厂模式,其它很少用,下面是一个简单的实现,不对的地方,欢迎交流。
代码如下

function List(){
this.data=[];
}
List.prototype={
add:function(){
var args=[].slice.call(arguments)
this.data=this.data.concat(args);
},
remove:function(i){
this.data.splice(i,1);
},
iterator:function(){
return new Iterator(this);
}
} function Iterator(list){
this.list=list;
this.cur=0;
};
Iterator.prototype={
hasNext:function(){
return this.cur<this.list.data.length-1;
},
next:function(){
if(this.hasNext()){
return this.list.data[this.cur++];
}
throw new Error('已经到底了~');
},
remove:function(){
this.list.remove(this.cur);
}
} var list1=new List();
var it=list1.iterator();
list1.add(3,2,3,4,1,6,10,8,9);
it.next();//3
it.next();//2
it.next();//3

[Effective JavaScript 笔记]第24条:使用变量保存arguments对象的更多相关文章

  1. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  2. [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法

    前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数argument ...

  3. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  4. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  5. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  6. [Effective JavaScript 笔记]第2章:变量作用域--个人总结

    前言 第二章主要讲解各种变量作用域,通过这章的学习,接触到了很多之前没有接触过的东西,比如不经常用到的eval,命名函数表达式,with语句块等,下面是一个列表,我对各节的一点点个人总结,很多都是自己 ...

  7. [Effective JavaScript 笔记]第22条:使用arguments创建可变参数的函数

    第21条讲述使用可变参数的函数average.该函数可处理任意数量的参数并返回这些参数的平均值. 如何创建可变参数的函数 1.实现固定元数的函数 书上的版本 function averageOfArr ...

  8. [Effective JavaScript 笔记]第54条:将undefined看做“没有值”

    undefined值很特殊,每当js无法提供具体的值时,就会产生undefined. undefined值场景 未赋值的变量的初始值即为undefined. var x; x;//undefined ...

  9. [Effective JavaScript 笔记] 第10条:避免使用with

    with特性,提供的任何“便利”都更让其变得不可靠和低效率. with语句的用法,可以很方便地避免对对象的重复引用.上面的代码整理成下面的形式 function status(info){ var w ...

随机推荐

  1. 微软发布独立Android模拟器 为开发者提供测试

    微软发布了 Visual Studio 2015 正式版,除了免费的社交版之外,另外也有付费的专业版.这套工具除了提供 Windows 应用程序的整合环境之外,你也可以利用它来开发 Android 程 ...

  2. 最新微信小程序(应用号)视频教程,实战教程

    1.1课程介绍,定个小目标            http://v.youku.com/v_show/id_XMTc2NzIwNDk1Ng==.html 1.2开发文档简读,了解全貌       ht ...

  3. .NET 关键字

    一.base关键字 可以通过base关键字访问上一级父类方法的访问.静态static函数无法调用base 二.new 关键字new new有2个作用. new运算符   用来分配内存空间和初始化对象. ...

  4. 要期末了搞不了OI了额……

    TAT~~~~~~期中完挂,求RP求期末逆袭

  5. Bootstrap3.0学习第二十五轮(JavaScript插件——折叠)

    详情请查看http://aehyok.com/Blog/Detail/31.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...

  6. Bootstrap3.0学习第七轮(按钮)

    详情请查看http://aehyok.com/Blog/Detail/13.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...

  7. 第二十四课:jQuery.event.remove,dispatch的源码解读

    本课还是来讲解一下jQuery是如何实现它的事件系统的.这一课我们先来讲一下jQuery.event.remove的源码解读. remove方法的目的是,根据用户传参,找到事件队列,从里面把匹配的ha ...

  8. angular_routerJS_学习

    //这几天看了angularjs和backbone,大看了解了knockout和emberjs,刚刚上网看到了一个angular的router的demo,现在顺便记下来 <!--- DEMO_I ...

  9. EasyUI——实现展示后台数据代码

    下面是View显示代码: @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml" ...

  10. BZOJ2456 mode

    Description 给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数. Input 第1行一个正整数n. 第2行n个正整数用空格隔开. Output 一行一个正整数 ...