它仅在#toString
上发生,并且仅当我(试图)通过类似missingMethod
的{{1}}访问它时出现。
我有一个名为trap
的工厂,该工厂使用大量方法返回对象的createIterface
。在这些方法中,我同时拥有Proxy
和#toString()
。 #id()
返回具有与调用者相同属性的#id
,并且效果很好; interface
应该将我的#toString
转换为字符串,但是失败。
interface
的所有方法-包括interface
和#id
-都在#toString
属性内。我这样做是为了调试目的:
#Symbol.for("__methods")
抛出的错误表明它不能(隐式)将Symbol转换为String(这是正确的)。事实是,const __methods = Symbol.for("__methods");
const missingMethod = ({
get: (obj, prop) => Reflect.has(obj, prop)
? Reflect.get(obj, prop)
: Reflect.has(obj[__methods], prop)
? Reflect.get(obj[__methods], prop)
: console.log(`No #${prop} property exists.`)
});
const createInterface = (...props) => new Proxy({
...props,
[__methods]: {
id: () => createInterface (...props),
toString: () => `Interface(${ props.toString() })`
}
}, missingMethod);
const interface = createInterface(0, 1, 2);
interface.id(); //works
interface.toString(); //error: Cannot convert a Symbol value to a string
不是符号。但是,有一个著名的符号称为#toString
,它定义了#toStringTag
的行为。当我用其他方法实现它时,我的Object#toString()
被忽略,#toString()
返回interface
:
'[object Object]'
如果我对// see code above
const createInterface = (...props) => new Proxy({
...props,
[__methods]: {
id: () => createInterface (...props),
toString: () => `Interface(${ props.toString() })`,
[Symbol.toStringTag]: () => "Interface"
}
}, missingMethod);
const interface = createInterface(0, 1, 2);
interface.id(); //works
interface.toString(); //bug: '[object Object]'
之外的方法进行编码,则一切正常:
__methods
除了一些奇怪的浏览器错误(我正在运行最新的Chrome,在撰写本文时,它是71.0.3578.98版),我不知道为什么会这样或如何解决。
有人可以帮忙吗?
答案 0 :(得分:4)
问题是首先访问interface.toString
是
get: (obj, prop) => Reflect.has(obj, prop)
? Reflect.get(obj, prop)
: Reflect.has(obj[__methods], prop)
...
您期望interface.toString
落入此处的三进制并到达_methods
,但是由于Reflect.has(obj, 'toString')
,true
的值将为Object.prototype.toString
。然后,再次通过代理的getter操作 调用对象上的该函数,搜索要调用的#toStringTag
。吸气剂经过所有三元分析,一无所获,因此抛出异常
console.log(`No #${prop} property exists.`)
因为prop
是符号,并且无法串联。
一种可能性是使用不继承自Object.prototype
的对象:
const obj = Object.create(null);
const createInterface = (...props) => new Proxy(
Object.assign(obj, {
...props,
[__methods]: {
id: () => createInterface (...props),
toString: () => `Interface(${ props.toString() })`
}
})
, missingMethod
);
const __methods = Symbol.for("__methods");
const missingMethod = ({
get: (obj, prop) => Reflect.has(obj, prop)
? Reflect.get(obj, prop)
: Reflect.has(obj[__methods], prop)
? Reflect.get(obj[__methods], prop)
: console.log(`No #${prop} property exists.`)
});
const obj = Object.create(null);
const createInterface = (...props) => new Proxy(
Object.assign(obj, {
...props,
[__methods]: {
id: () => createInterface (...props),
toString: () => `Interface(${ props.toString() })`
}
})
, missingMethod
);
const interface = createInterface(0, 1, 2);
interface.id(); //works
console.log(interface.toString());
另一种可能是让吸气剂进行hasOwnProperty
检查而不是Reflect.has
检查(Reflect.has
与in
基本相同,而{{1} }将是'toString'
几乎所有对象):
in
get: (obj, prop) => obj.hasOwnProperty(prop)
第三种可能性是,确保通过const __methods = Symbol.for("__methods");
const missingMethod = ({
get: (obj, prop) => obj.hasOwnProperty(prop)
? Reflect.get(obj, prop)
: Reflect.has(obj[__methods], prop)
? Reflect.get(obj[__methods], prop)
: console.log(`No #${prop} property exists.`)
});
const createInterface = (...props) => new Proxy({
...props,
[__methods]: {
id: () => createInterface (...props),
toString: () => `Interface(${ props.toString() })`,
}
}, missingMethod);
const interface = createInterface(0, 1, 2);
interface.id(); //works
console.log(interface.toString());
方法在初始Reflect.has
中找到的属性不是 :
Object.prototype
get: (obj, prop) => Reflect.has(obj, prop) && Reflect.get(obj, prop) !== Object.prototype[prop]