此代码如何运作?
if (!(args in pad)) {
pad[args] = self.apply(obj, arguments);
}
args是数组,但它不应该是一个字符串,因为它是JS对象的一个键?
怎么检查工作? array in object
?
完整背景here:
Function.prototype.memoize = function() {
var pad = {};
var self = this;
var obj = arguments.length > 0 ? arguments[i] : null;
var memoizedFn = function() {
// Copy the arguments object into an array: allows it to be used as
// a cache key.
var args = [];
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
// Evaluate the memoized function if it hasn't been evaluated with
// these arguments before.
if (!(args in pad)) {
pad[args] = self.apply(obj, arguments);
}
return pad[args];
}
memoizedFn.unmemoize = function() {
return self;
}
return memoizedFn;
}
答案 0 :(得分:4)
args转换为字符串,对于数组意味着:
[1,2,3].toString() == "1,2,3"; //true
在in
中使用时会自动转换为字符串:
( [1,2,3] in ( {"1,2,3":""} ) ) //true
这是因为in
运算符只接受左侧的字符串。
使用pad[args]
时,会再次发生相同的转换,因为对象键只能是字符串。例如,当您使用array[1]
时,实际发生的是array["1"]
,因为该数字将转换为字符串。
答案 1 :(得分:3)
这应该清楚了:
var a = [1,2,3]
var s = "" + a
var x = {}
x[a] = "hello world"
alert(s in x)
也就是说,属性名称总是字符串,根据需要转换为 。 (请注意,“裸”对象通常不会用作属性名称,因为它们缺少适当的字符串化 - 但请参阅下文,了解如何使用toString/valueOf
。)
ECMAScript 5th Edition Specification找到像这样的“简单”的东西真的很毛茸茸 - 这是我所知道的最令人费解的措辞过多的语言规范 - 但它归结为接受属性名称的各种制作(作为表达式)。
请参阅第11.2.1节:属性访问者
生成MemberExpression:MemberExpression [Expression]的计算方法如下:
[...] 6. 让propertyNameString为 ToString (propertyNameValue)。 [...] 8. 返回一个值 [...] ,其引用名称为 propertyNameString [...]
第11.8.7节:运算符
ShiftExpression中的生产RelationalExpression:RelationalExpression [aka propertyNameValue]的计算方法如下:
[...] 6. 返回使用参数 ToString (lval [aka propertyNameValue])调用rval的[[HasProperty]]内部方法的结果。
现在,出现以下链以确定ToString(propertyNameValue)
的结果(请参阅规范以获取所有细节):
ToString
,第9.8节ToPrimitive
,第9.1节[[DefaultValue]]
(带有“字符串”提示),第8.12.8节toString()
或valueOf()
(第一个可赎回的)的结果同样的ToString
流程适用于所有对属性的访问权限 - 无论是obj[prop]
还是obj.HasOwnProperty(prop)
还是prop in obj
。
快乐的编码。