gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 15:54:17 26 4
gpt4 key购买 nike

有没有办法在 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。有办法吗?

最佳答案

不幸的是,根据对 ToPrimitive 的所有引用的规范搜索,除了在 javascript 中繁琐地重新实现算法之外似乎没有任何选择。

一个(大部分未经测试的)示例实现可能是:

// a primitive is anything that's not an object, but typeof has two quirks
// to be cautious of:
// - for a callable object it returns 'function' rather than 'object'
// - typeof null is 'object' even though null is a primitive
const isPrimitive = ( value ) =>
typeof value === 'object' ? value === null : typeof value !== 'function';

const toPrimitive = ( value, hint='default' ) => {
// if value is already a primitive, we're done
if( isPrimitive( value ) )
return value;

// if value[ Symbol.toPrimitive ] exists (is not undefined or null)
let method = value[ Symbol.toPrimitive ];
if( method != null ) { // using != instead of !== is intentional

// then call value[ Symbol.toPrimitive ]( hint )
let result = Reflect.apply( method, value, [ hint ] );
if( isPrimitive( result ) )
return result;

// if it doesn't return a primitive, do not fall back to legacy
// methods but just throw an error

} else {

// if value[ Symbol.toPrimitive ] doesn't exist, try the legacy
// valueOf() and toString() methods, in that order unless hint
// is 'string' in which case toString() is tried first.
//
// for these we need to be more garbage-tolerant: if the first
// legacy method is a non-function or returns a non-primitive,
// just ignore it and move on to the second one.

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 != null ) // 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;
};

并将抛出异常留给调用者(Javascript 运行时)。

请注意,method != null(或 method != undefined)只是一种更简洁(并且稍微更有效)的方式来编写 method != = undefined && 方法 !== null.

注意避免写这样的东西:

    if( value[ Symbol.toPrimitive ] != null )
return value[ Symbol.toPrimitive ]( hint );

因为这执行了两次 value[ Symbol.toPrimitive ] 属性查找,这是与规范的明显差异(并且两次执行相同的属性查找可能会产生不同的值)。

也不要试图编写 method.call( value ) 而不是 Reflect.apply( method, value, [] ) 因为那样不会有如果该方法(粗鲁地)覆盖其 call 方法,则结果相同。使用 Function.prototype.call.call( method, value ) 很好,但我不认为这是对使用 Reflect.apply 的改进。

您可以将 hint === 'string' 优化为:

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

因为我认为应该与规范中当前的提示兼容 ToPrimitive 的所有使用,但它有可能在未来中断(例如,如果 future 的规范引入类似于 python3 的 bytes 类型的字节串)。我也不知道这是否真的更快,这需要测试。

关于javascript - 有没有办法在 Javascript 中调用 toPrimitive?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52573030/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com