试图理解闭包.谁能告诉我这个密码
Trying to understand closures. Could somebody walk me through this code?
下面是一段摘自reddit帖子的javascript代码:
function Stream() {
var data = [],
listeners = [];
function push( new_data ) {
var result = data.push( new_data );
callListeners( new_data, result );
return result;
}
function addListener( listener ) {
return listeners.push( listener );
}
function callListeners( ) {
var length = listeners.length,
result = [],
action = null;
while ( length-- ) {
action = listeners[ length ];
result.push( action.apply( null, arguments) );
}
return result;
}
return {
push : push,
addListener: addListener
}
}
var foo = Stream();
foo.addListener( function( new_data ) {
alert( "added: " + new_data );
});
foo.push( "Hello World!" );
我认为在阅读了本教程之后,我对闭包有了一个微弱的理解,但是我就是不明白这段代码是如何工作的。当我试图在脑海中解析它时,我基本上被困在第6行:var result = data.push( new_data );
。
似乎 (strike -不知道有一个原生的data
只是一个数组在那一点data.push( foo )
是没有意义的。它不会无限递归吗?push
方法用于数组)下一行callListener
被调用时带有两个参数,但下面的函数没有参数。
如果有人有几分钟的话,你能抓住我的手,像我这个无知的傻瓜一样给我讲讲这些代码吗?现在,我甚至不确定我是否理解目的地。
数组是对象,它们有一个push()
方法。没什么特别的。
callListeners()
函数没有声明任何命名参数,但是JavaScript允许调用函数时使用比声明的参数更多的参数,并且完整的参数列表作为特殊名称arguments
可用。callListeners()
在action.apply()
调用中使用arguments
来调用action
函数,其参数列表与callListeners()
本身相同。callListeners()
的目的是你用一些参数调用它,它用这些参数调用listeners
数组中的所有函数。
Stream()
返回的对象有两个方法,push()
和addListener()
,可以"看到"相同的data
和listeners
数组,即使这些数组没有存储在调用方法的对象中。对Stream()
的两次调用将返回两个对象,其方法看到不同的 data
和listeners
数组。
> function Stream() {
> var data = [],
> listeners = [];
>
> function push( new_data ) {
> var result = data.push( new_data );
data
是对外部函数中数据的引用。data.push(...)
的返回值是添加new_data
后数组的长度。
> callListeners( new_data, result );
> return result;
> }
callListeners()
是对以下面的名称声明的函数的调用。
> function addListener( listener ) {
> return listeners.push( listener );
> }
这将listener
添加到listeners
,并返回listeners
数组的新长度。
> function callListeners( ) {
> var length = listeners.length,
> result = [],
> action = null;
> while ( length-- ) {
> action = listeners[ length ];
> result.push( action.apply( null, arguments) );
> }
> return result;
> }
上面的函数用传递给它的参数调用listeners
数组中的所有侦听器。它以相反的顺序调用它们(即,最后添加的一个首先调用,然后第二个最后调用,依此类推),这有点不寻常。
> return {
> push : push,
> addListener: addListener
> }
返回一个具有以下属性的对象:push
(其值是对名称为push的函数的引用)和addListener
(其值是对名称为addListener的函数的引用)
> }
>
>
> var foo = Stream();
按照约定,名称以大写字母开头的函数是构造函数,应该用new
操作符调用。流不是构造函数,所以应该以小写s开头。
> foo.addListener( function( new_data )
> {
> alert( "added: " + new_data ); });
调用foo.addListener
(这是对上面调用Stream()
时创建的"closed over"addListener函数的引用)并传递给它一个匿名函数。对返回值不做任何处理。
> foo.push( "Hello World!" );
调用(关闭)push
函数并传递字符串"Hello World!"。然后push
调用callListeners()
,传递给它相同的字符串。然后callListeners
调用侦听器数组中的每个函数(到目前为止只有一个,上面添加的匿名函数),将提供给push()
的参数传递给它。"Hello World !").
所以结果是一个带有"added: Hello World!"的警告。
如果添加另一个侦听器,则调用foo.push()
将使用提供的参数调用两个侦听器,但顺序与添加的顺序相反。
首先,push
是Array类的一个方法:
通过添加给定元素并返回数组的新长度来改变数组。
因此,var result = data.push( new_data );
只是将new_data
添加到data
之后,并将result
设置为data
中的新元素数。
callListeners
位很棘手。action
将是一个函数,它将通过在该函数上使用apply
方法来调用(注意:函数在JavaScript中是对象)。你还会看到arguments
,这是一个特殊的变量,它是:
类数组对象,与传递给函数的实参相对应。
所以,如果你想自己解包参数列表(比如在Perl中使用@_
,或者在C或c++中使用变量参数列表),或者如果你只是计划将完整的参数列表传递给想要数组的其他人,那么你可以使用arguments
。通常你会说:
var a = Array.prototype.slice.call(arguments);
显式地将arguments
转换为实际数组。然而,在这种情况下,apply
很乐意采用原始的arguments
伪数组,因此不需要"切片强制转换"。
JavaScript数组有一个本地的push()
方法。查看这篇文章…
…所以代码不是递归地调用function push( new_data ){}
,而是引用数组的原生push()
方法。
如果它是递归的,它将改为var result = this.push( new_data );
,这将使它成为无限的:)
我希望这对你有帮助。斯托伊
- 有人能告诉我如何在cent-os中打开扩展名为.dat的FIle吗
- 谷歌关闭注释赢得'Don’不要告诉我;I’我错了
- JavaScript:有人能告诉我我的代码出了什么问题吗?
- 我需要将这两个函数从javascript更改为JQuery,任何人都可以告诉我如何转换
- 有人可以告诉我如何调试这个 html 表单/javascript 组合
- 有人能告诉我如何使用getCurrentPosition的watchposition()函数吗
- 有人能告诉我为什么点击按钮时不提交这份表格吗
- 如何在函数中编写 if/else 语句,告诉我一个数字是否可以被 2 整除(在 javascript 中)
- 有人能告诉我如何实现这个Javascript吗?HTML CSS
- PHP一直告诉我值为空
- 我想隐藏一个没有'没有js文件中的id.我想不通,请告诉我
- jQuery告诉我某个东西在数组中,而它不是't
- 我正在使用 $scope.$apply 在 http 调用后更新对象数组.谁能告诉我正确的方法
- 当浏览器进入后台时,什么事件告诉我
- 有人可以告诉我这个java脚本有什么问题吗?
- 实现滚动条,但光标根本没有移动?另外,如果可以的话,请告诉我如何在此嵌入鼠标滚动
- 我想更新一个.json文件,请告诉我如何去做
- 你能告诉我什么是函数(el)吗?
- 拉斐尔气泡图查询(谁能告诉我这到底是什么图表?
- 试图理解闭包.谁能告诉我这个密码