有没有办法在Javascript中调用toPrimitive?

时间:2018-09-29 22:23:16

标签: javascript ecmascript-6

有没有一种方法可以对Javascript中的值调用toPrimitive?

为什么?

我在项目中使用代理。

function makeProxy(unknown_value) {
    let proxy_target = ()=>{};
    proxy_target.inner = unknown_value;
    proxy_target.my_data = 123456;

    return new Proxy(proxy_target, some_proxy_handler);
}

let proxied_value = makeProxy(<? something unknown ?>);

此代理将所有呼叫重定向到“内部”。 最终我被这样的事情感动了:

console.log(1+proxied_value);

此处有Javascript调用

(1)
proxied_value.get(proxy_target, Symbol.toPrimitive)

因为Javascript想要尝试将proxied_value转换为某个值以对其执行“ +”。对于proxy_target.inner,此操作是可能的

所以我想将此呼叫(1)重定向到:

(something like)
Object.toPrimitive( proxy_target.inner );

但是我发现没有办法直接调用toPrimitive。 有办法吗?

2 个答案:

答案 0 :(得分:2)

不幸的是,基于在规范中搜索到的所有对ToPrimitive的引用,除了乏味地在javascript中重新实现该算法之外,似乎没有其他选择。

(大多数未经测试的)示例实现可能是:

const isPrimitive = ( value ) =>
    value === null || ( typeof value !== 'object' && typeof value !== 'function' );

const toPrimitive = ( value, hint='default' ) => {
    if( isPrimitive( value ) )
        return value;

    let method = value[ Symbol.toPrimitive ];
    if( method != undefined ) {  // using != instead of !== is intentional
        let result = Reflect.apply( method, value, [ hint ] );
        if( isPrimitive( result ) )
            return result;
    } else {
        method = value[ hint === 'string' ? 'toString' : 'valueOf' ];
        if( typeof method === 'function' ) {
            let result = Reflect.apply( method, value, [] );
            if( isPrimitive( result ) )
                return result;
        }

        method = value[ hint === 'string' ? 'valueOf' : 'toString' ];
        if( typeof method === 'function' ) {
            let result = Reflect.apply( method, value, [] );
            if( isPrimitive( result ) )
                return result;
        }
    }

    throw new TypeError("Cannot convert object to primitive value");
};

如果您不需要完全精确的ToPrimitive实现,而只需要在功能上与应用程序等效时,就可以简化实现为:

const toPrimitive = ( value, hint='default' ) => {
    if( isPrimitive( value ) )
        return value;

    let method = value[ Symbol.toPrimitive ];
    if( method != undefined )  // using != instead of !== is intentional
        return Reflect.apply( method, value, [ hint ] );

    method = value[ hint === 'string' ? 'toString' : 'valueOf' ];
    if( typeof method === 'function' ) {
        let result = Reflect.apply( method, value, [] );
        if( isPrimitive( result ) )
            return result;
    }

    method = value[ hint === 'string' ? 'valueOf' : 'toString' ];
    if( typeof method === 'function' )
        return Reflect.apply( method, value, [] );

    return value;
};

并将抛出异常留给调用方。

您也许还可以将hint === 'string'的情况优化为:

const toPropertyKey = ( value ) => {
    return Reflect.ownKeys( { [value]: 0 } )[0];
};

因为我认为应该与ToPrimitive的所有用法兼容,并且提示在规范中目前为 ,但将来可能会中断(例如,如果将来的规范引入了类似于python3的bytes类型的字节串)。我也不知道这实际上是否更快,需要测试。

答案 1 :(得分:0)

 proxy_target[Symbol.toPrimitive]("number")

在get处理程序内部,您可以只使用Reflect:

 get(...args) {
   // ...
   return Reflect.get(...args);
 }