通过 getter 和自定义 toString() 访问的对象 属性 的 .length 未定义

.length of object property accessed through getter and custom toString() is undefined

这是一个示例 JavaScript 对象:

var foo = {
    valueObj: {
        value: 'hello',
        toString: function() { return this.value }
    },
    get val() { 
        return this.valueObj; 
    }
}

我需要获取存储在 foo.valueObj.value 中的字符串 'hello' 的长度。我需要使用以下确切语法访问它:

foo.val.length

foo.val 应该 return valueObj,确实如此。调用 foo.val.length 然后应该调用 valueObj 的自定义 toString 方法,returning 'hello',.length 应该 return 该字符串的长度。但事实并非如此!

以下内容确实有效,证明当需要原始值时,确实通过 getter 调用了 toString() 方法:

foo.val + ' world'
//=>'hello world'

为什么.length不调用toString()方法?我怎样才能在这里实现我所需要的?谢谢!

Calling foo.val.length then should invoke the custom toString method of valueObj

没有。 foo.val returns 一个对象。并且尝试访问该对象的 属性 length 不会调用 toString 方法。

但是你可以使用 expr + '' 强制转换为字符串,这将调用 toString:

(foo.val+'').length

this.valueObj 没有 length 属性。询问其 length 属性 不会导致自动转换为字符串(而连接字符串会导致转换为字符串)。

如果您确实需要使用那种确切的语法(并且不能首先执行对字符串的强制转换),那么简单的解决方案是将 length getter 添加到 valueObj .

var foo = {
    valueObj: {
        value: 'hello',
        toString: function() { return this.value },
        get length() {
            return this.toString().length
        }
    },
    get val() { 
        return this.valueObj; 
    }
}

不,访问名称为 length 的 属性 不会调用 .toString() 方法。它访问 length 属性.

如果您希望.length易于访问,您可以包含它:

var foo = {
    valueObj: {
        value: 'hello',
        toString: function() { return this.value; },
        get length() { return this.value.length; }
    },
    get val() { 
        return this.valueObj; 
    }
};

请注意,这可能会产生意想不到的后果。如果某些库具有数字 .length 属性 并尝试使用数字索引迭代它们(但您的对象没有数字索引),则某些库将假定对象为 "array-like"。你可能最好实际使用 .toString() 方法(或者甚至只是 .value)而不是试图让你的对象假装它是一个字符串。