如何将数组用作属性名称?

时间:2011-10-17 01:17:32

标签: javascript

此代码如何运作?

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;
}

2 个答案:

答案 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)的结果(请参阅规范以获取所有细节):

  1. ToString,第9.8节
  2. ToPrimitive,第9.1节
  3. (对象)[[DefaultValue]](带有“字符串”提示),第8.12.8节
  4. (对象)toString()valueOf()(第一个可赎回的)的结果
  5. 同样的ToString流程适用于所有对属性的访问权限 - 无论是obj[prop]还是obj.HasOwnProperty(prop)还是prop in obj

    快乐的编码。