Node.js 带方括号的全局变量和函数 - 为什么这样做有效?
Node.js global variables and functions with square brackets - why does this work?
我的模块 returns 一个回调对象,具有以下伪代码的结构:
module.exports=function(){
global.foo=function(){
var callbacks=Array.prototype.slice.call(arguments,1);
var conf=arguments[0];
return global[callbacks.shift()].apply(null,[conf,callbacks]);
}
global.bar=function(){
var callbacks=Array.prototype.slice.call(arguments,1);
var conf=arguments[0];
return global[callbacks.shift()].apply(null,[conf,callbacks]);
}
// This one is where i ran into trouble
global.foobar=function(){
var callbacks=Array.prototype.slice.call(arguments,1);
var conf=arguments[0];
// right here
if(callbacks.length===[].length){
return global[callbacks.shift()].apply(null,[conf,callbacks]);
}
}
var conf={'pseudo':'object'};
return global['foo'](conf,'foo','bar','foobar');
}
在 foobar
之前一切正常,发生的事情是当我开始检查是否还有回调时 - 因为如果有,我想调用它们 - callbacks.length
是 1在此刻。这对我来说没有意义,我发现那时 callbacks
实际上等于 [[]]
。我不知道为什么要退货,所以我想我有两个问题。谁能看出为什么 callbacks
等于 [[]]
?
我在此过程中发现的是,在全局命名空间中使用作为函数调用的字符串时 - 如 var bar='foo'
; global[bar]()
调用 global.foo()
- 忽略多个括号。例如,global[[[[[[['foo']]]]]]] === global['foo']
。同样奇怪的是(至少对我而言),以下内容:
// With
global.bar='foo';
global.foo=function(){return true;}
//the following
global[global[bar]]()
// throws a TypeError: undefined is not a function
None 对我来说很有意义。
我知道这个问题最后问了三个问题,有点乱,但坦白说我有点糊涂,我不太确定我想问我想知道的东西,所以我什么都说了。
我的主要问题是关于多个括号,以及它为什么有效。
谢谢
My main questions is regarding the multiple brackets, and why that
works.
多个括号之所以有效,是因为它试图进行字符串转换以获得 属性 名称。因此,无论您有多少个嵌套数组,它最终都会在每个数组上调用 .toString()
,并且由于内部数组只有一个包含字符串的项目,因此多个 .toString()
调用只会结束解析为内部字符串。
下面是同一概念在浏览器中的演示:
window.foo = "hi"
document.write(window[[[[["foo"]]]]]);
进一步解释:
["foo"].toString() === "foo";
那么,那么:
[["foo"].toString()].toString() === "foo"
但是,如果外面的 .toString()
存在,它已经将东西驱动到一个字符串中,因此您可以删除内部的 .toString()
,这样您会得到:
[["foo"]].toString() === "foo"
然后,您可以根据需要嵌套任意多的层级,只要外层的某些东西将其驱动为字符串即可。
而且,由于 属性 名称始终是字符串,当您这样做时:
global[[[[[[['foo']]]]]]]
你最终要求的是一个可以在 global
对象上查找的 属性 名称,因为 属性 名称是一个字符串,所以调用 .toString()
在外部阵列上。当外部数组将其唯一的项目转换为字符串时,它要求将其自身转换为字符串,因此:
global[[[[[[['foo']]]]]]]
变成这样:
global[[[[[[['foo'].toString()].toString()].toString()].toString()].toString()].toString()]
这有望解释为什么你最终只得到这个:
global["foo"]
仅供参考,如果您查看 Array.prototype.toString()
的 ES5/ES6 规范,它最终会调用 array.join()
,对于单个元素数组,它最终会执行 .toString()
在那个单个元素上,这就是它如何导致所有嵌套数组只对自己调用 .toString()
。外部数组在第一个嵌套数组上调用 .toString()
,它在它的单个项目上调用 .toString()
,这是下一个嵌套数组,依此类推,直到它最终到达从所有 .toString()
来电。而且,嵌套的数组深度并不重要。
Array.prototype.toString()
规格参考:http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.tostring
Array.prototype.join()
的规范参考,由 Array.prototype.toString()
调用:http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.join
在你这里的其他场景中:
// With
global.bar='foo';
global.foo=function(){return true;}
//the following
global[global[bar]]()
// throws a TypeError: undefined is not a function
None of that makes sense to me.
这是 global[global[bar]]()
一次一件的情况:
bar
解析为字符串 'foo'
.
因此,global[bar]
解析为 global['foo']
,这是您的函数。
但是,然后你尝试像这样对它做另一个全局引用 global[global[bar]]
,那么你实际上是在尝试做:
global[yourfunction]
或
global[global.foo]
这将尝试将您的函数转换为字符串并在 global
对象上查找 属性。那将是 undefined
。因此,您将尝试执行 undefined()
这是一个类型错误,因为 undefined
不是函数。
在这种情况下有效的是:
global[bar]()
我的模块 returns 一个回调对象,具有以下伪代码的结构:
module.exports=function(){
global.foo=function(){
var callbacks=Array.prototype.slice.call(arguments,1);
var conf=arguments[0];
return global[callbacks.shift()].apply(null,[conf,callbacks]);
}
global.bar=function(){
var callbacks=Array.prototype.slice.call(arguments,1);
var conf=arguments[0];
return global[callbacks.shift()].apply(null,[conf,callbacks]);
}
// This one is where i ran into trouble
global.foobar=function(){
var callbacks=Array.prototype.slice.call(arguments,1);
var conf=arguments[0];
// right here
if(callbacks.length===[].length){
return global[callbacks.shift()].apply(null,[conf,callbacks]);
}
}
var conf={'pseudo':'object'};
return global['foo'](conf,'foo','bar','foobar');
}
在 foobar
之前一切正常,发生的事情是当我开始检查是否还有回调时 - 因为如果有,我想调用它们 - callbacks.length
是 1在此刻。这对我来说没有意义,我发现那时 callbacks
实际上等于 [[]]
。我不知道为什么要退货,所以我想我有两个问题。谁能看出为什么 callbacks
等于 [[]]
?
我在此过程中发现的是,在全局命名空间中使用作为函数调用的字符串时 - 如 var bar='foo'
; global[bar]()
调用 global.foo()
- 忽略多个括号。例如,global[[[[[[['foo']]]]]]] === global['foo']
。同样奇怪的是(至少对我而言),以下内容:
// With
global.bar='foo';
global.foo=function(){return true;}
//the following
global[global[bar]]()
// throws a TypeError: undefined is not a function
None 对我来说很有意义。
我知道这个问题最后问了三个问题,有点乱,但坦白说我有点糊涂,我不太确定我想问我想知道的东西,所以我什么都说了。
我的主要问题是关于多个括号,以及它为什么有效。
谢谢
My main questions is regarding the multiple brackets, and why that works.
多个括号之所以有效,是因为它试图进行字符串转换以获得 属性 名称。因此,无论您有多少个嵌套数组,它最终都会在每个数组上调用 .toString()
,并且由于内部数组只有一个包含字符串的项目,因此多个 .toString()
调用只会结束解析为内部字符串。
下面是同一概念在浏览器中的演示:
window.foo = "hi"
document.write(window[[[[["foo"]]]]]);
进一步解释:
["foo"].toString() === "foo";
那么,那么:
[["foo"].toString()].toString() === "foo"
但是,如果外面的 .toString()
存在,它已经将东西驱动到一个字符串中,因此您可以删除内部的 .toString()
,这样您会得到:
[["foo"]].toString() === "foo"
然后,您可以根据需要嵌套任意多的层级,只要外层的某些东西将其驱动为字符串即可。
而且,由于 属性 名称始终是字符串,当您这样做时:
global[[[[[[['foo']]]]]]]
你最终要求的是一个可以在 global
对象上查找的 属性 名称,因为 属性 名称是一个字符串,所以调用 .toString()
在外部阵列上。当外部数组将其唯一的项目转换为字符串时,它要求将其自身转换为字符串,因此:
global[[[[[[['foo']]]]]]]
变成这样:
global[[[[[[['foo'].toString()].toString()].toString()].toString()].toString()].toString()]
这有望解释为什么你最终只得到这个:
global["foo"]
仅供参考,如果您查看 Array.prototype.toString()
的 ES5/ES6 规范,它最终会调用 array.join()
,对于单个元素数组,它最终会执行 .toString()
在那个单个元素上,这就是它如何导致所有嵌套数组只对自己调用 .toString()
。外部数组在第一个嵌套数组上调用 .toString()
,它在它的单个项目上调用 .toString()
,这是下一个嵌套数组,依此类推,直到它最终到达从所有 .toString()
来电。而且,嵌套的数组深度并不重要。
Array.prototype.toString()
规格参考:http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.tostring
Array.prototype.join()
的规范参考,由 Array.prototype.toString()
调用:http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.join
在你这里的其他场景中:
// With
global.bar='foo';
global.foo=function(){return true;}
//the following
global[global[bar]]()
// throws a TypeError: undefined is not a function
None of that makes sense to me.
这是 global[global[bar]]()
一次一件的情况:
bar
解析为字符串 'foo'
.
因此,global[bar]
解析为 global['foo']
,这是您的函数。
但是,然后你尝试像这样对它做另一个全局引用 global[global[bar]]
,那么你实际上是在尝试做:
global[yourfunction]
或
global[global.foo]
这将尝试将您的函数转换为字符串并在 global
对象上查找 属性。那将是 undefined
。因此,您将尝试执行 undefined()
这是一个类型错误,因为 undefined
不是函数。
在这种情况下有效的是:
global[bar]()