Effective JavaScript Item 24 使用一个变量来保存arguments的引用

本系列作为Effective JavaScript的读书笔记。

假设需要一个API用来遍历若干元素,像下面这样:

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

相应的实现可以是:

function values() {
	var i = 0, n = arguments.length;
	return {
		hasNext: function() {
			return i < n;
		},
		next: function() {
			if (i >= n) {
				throw new Error("end of iteration");
			}
			return arguments[i++]; // wrong arguments
		}
	};
}

但是执行的实际情况却是:

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

原因在于:对于arguments对象的赋值是隐式完成的。

在next方法内部,使用了arguments,然而此arguments和values方法开始处的arguments并不是一个对象。

解决方法也很简单,就是将需要访问的arguments使用另外一个变量进行引用。然后通过闭包的性质在其嵌套的函数中进行访问就可以了,像下面这样:

function values() {
	var i = 0, n = arguments.length, a = arguments;
	return {
		hasNext: function() {
			return i < n;
		},
		next: function() {
			if (i >= n) {
				throw new Error("end of iteration");
			}
			return a[i++];
		}
	};
}
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // 1
it.next(); // 4
it.next(); // 1

总结:

  1. 当在嵌套的函数中使用arguments时,注意arguments的实际指向
  2. 需要在嵌套的函数中使用外部函数的arguments时,将外部函数的arguments对象保存到一个变量中,让嵌套函数进行访问

时间: 2024-11-11 06:46:03

Effective JavaScript Item 24 使用一个变量来保存arguments的引用的相关文章

Effective JavaScript Item 20 使用call方法来绑定this变量

本系列作为Effective JavaScript的读书笔记. 通常而言,一个函数中this的指向和该函数的调用类型相关,比如当函数直接作为函数被调用时,this一般指向的是全局对象(StrictMode时指向undefined):当函数作为方法被调用时(即x.method()这种形式),this指向的是x:当函数作为构造方法被调用时,this指向的是一个新创建的对象. 但是在一些场合,需要指定this的指向,比如下面的代码需要将this指向一个对象obj,一个简单的办法如下: obj.temp

Effective JavaScript Item 25 使用bind方法来得到一个固定了this指向的方法

本系列作为Effective JavaScript的读书笔记. 当需要将方法抽取出来作为回调函数使用的时候,常常会因为this的指向不明而发生错误,比如: var buffer = { entries: [], add: function(s) { this.entries.push(s); }, concat: function() { return this.entries.join(""); } }; 如果想利用其中的add作为回调函数对一组数据进行添加: var source

Effective JavaScript Item 27 使用闭包而不是字符串来封装代码

本系列作为Effective JavaScript的读书笔记. 对于代码封装,在JavaScript中有两种方式可以办到.第一种就是使用function,第二种则是利用eval()函数,传入到该函数的字符串参数可以是一段代码. 当对使用哪种方式犹豫不决时,使用function.因为使用字符串的一个重要缺点是,传入的字符串并不是一个闭包,而function则可以代表一个闭包.关于闭包的特点,在Item 11中进行了描述. 下面是一段使用字符串来封装代码的例子: function repeat(n,

Effective JavaScript Item 13 使用即时调用的函数表达式(IIFE)来创建局部域

本系列作为Effective JavaScript的读书笔记. 所谓的即时调用的函数表达式,这个翻译也许不太准确,它对应的英文原文是Immediately Invoked Function Expression (IIFE).下文也使用IIFE来表达这一概念. 首先看一个程序: function wrapElements(a) { var result = [], i, n; for (i = 0, n = a.length; i < n; i++) { result[i] = function

Effective JavaScript Item 37 认识this的隐式指向

本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔,所以在实现CSV Reader时,需要支持不同的分隔符.那么,很自然的一种实现就是将分隔符作为构造函数的参数. function CSVReader(separators) { this.separators = separators || [","]; this.regexp = new RegExp(this.separators.map(function(sep) { retu

Effective JavaScript Item 22 使用arguments来创建接受可变参数列表的函数

本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变参数列表函数average,它实际上只声明了一个数组作为参数,但是利用apply方法,实际上可以接受若干元素作为参数: function averageOfArray(a) { for (var i = 0, sum = 0, n = a.length; i < n; i++) { sum += a[i]; } return sum / n; } averageOfArray.a

Effective JavaScript Item 11 掌握闭包

本系列作为Effective JavaScript的读书笔记. 掌握闭包,需要知道以下几个关键点: JavaScript允许在当前的function中访问该function外部的变量. function makeSandwich() { var magicIngredient = "peanut butter"; function make(filling) { return magicIngredient + " and " + filling; } return

Effective JavaScript Item 29 避免使用非规范的Stack Inspection属性

本系列作为Effective JavaScript的读书笔记. 由于历史原因,很多JavaScript执行环境中都提供了某些方式来查看函数调用栈.在一些环境中,arguments对象(关于该对象可以查看Item 22,23,24)上有两个额外的属性: arguments.callee - 它引用了正在被调用的函数 arguments.caller - 它引用了调用当前函数的函数 关于arguments.callee的使用,可以参考下面的代码: var factorial = (function(

Effective JavaScript Item 21 使用apply方法调用函数以传入可变参数列表

本系列作为Effective JavaScript的读书笔记. 下面是一个拥有可变参数列表的方法的典型例子: average(1, 2, 3); // 2 average(1); // 1 average(3, 1, 4, 1, 5, 9, 2, 6, 5); // 4 average(2, 7, 1, 8, 2, 8, 1, 8); // 4.625 而以下则是一个只接受一个数组作为参数的例子: averageOfArray([1, 2, 3]); // 2 averageOfArray([1