gpt4 book ai didi

javascript - 为什么 function.toString() 输出 "[native code]",而登录到控制台直接显示函数的源代码?

转载 作者:行者123 更新时间:2023-12-04 11:18:42 25 4
gpt4 key购买 nike

我决定为 YouTube 实时聊天创建一个用户脚本。这是代码:

const toString = Function.prototype.toString

unsafeWindow.setTimeout = function (fn, t, ...args) {
unsafeWindow.console.log(fn, fn.toString(), toString.call(fn))
unsafeWindow.fns = (unsafeWindow.fns ?? []).concat(fn)
return setTimeout(fn, t, ...args)
}
现在看看输出是什么样子的:
enter image description here
一些函数的输出是可以预测的,但看看其他的!当你做 console.log它,你会看到函数体,但如果你调用 fn.toString() ,您将看到 function () { [native code] } .
但为什么?该脚本在页面之前加载,因此 YouTube 的脚本无法替换这些方法。

最佳答案

这是因为那些函数已经传递给 Function.prototype.bind .

> (function () { return 42; }).toString()
'function () { return 42; }'
> (function () { return 42; }).bind(this).toString()
'function () { [native code] }'
bind方法将任意函数对象转换为所谓的绑定(bind)函数。调用绑定(bind)函数与调用原始函数具有相同的效果,除了 this参数和一定数量的初始位置参数(可能为零)将具有在创建绑定(bind)函数时固定的值。功能上, bind主要相当于:
Function.prototype.bind = function (boundThis, ...boundArgs) {
return (...args) => this.call(boundThis, ...boundArgs, ...args);
};
当然,上面的内容会在字符串转换后产生不同的值。根据 ECMA-262 11th Ed., §19.2.3.5 ¶2,绑定(bind)函数被指定为具有与 native 函数相同的字符串转换行为。 :

2. If func is a bound function exotic object or a built-in function object, then return an implementation-dependent String source code representation of func. The representation must have the syntax of a NativeFunction. […]

[…]

NativeFunction:

function PropertyName [~Yield, ~Await] opt ( FormalParameters [~Yield, ~Await] ) { [native code] }


当直接将函数打印到控制台(而不是字符串化)时,实现不受任何规范的约束:它可以以任何它希望的方式在控制台中呈现函数。 Chromium 的控制台,当被要求打印绑定(bind)函数时,为了方便起见,只显示原始未绑定(bind)函数的源代码。

证明这确实是在 YouTube 的案例中发生的事情有点麻烦,因为 YouTube 的 JavaScript 被混淆了,但并不是非常困难。我们可以打开 YouTube 的主站点,然后进入开发者控制台并安装我们的陷阱:
window.setTimeout = ((oldSetTimeout) => {
return function (...args) {
if (/native code/.test(String(args[0])))
debugger;
return oldSetTimeout.call(this, ...args);
};
})(window.setTimeout);
我们应该在 debugger 上获得成功。声明非常快。我在这个函数中击中了它:
g.mh = function(a, b, c) {
if ("function" === typeof a)
c && (a = (0, g.D)(a, c));
else if (a && "function" == typeof a.handleEvent)
a = (0, g.D)(a.handleEvent, a);
else
throw Error("Invalid listener argument");
return 2147483647 < Number(b) ? -1 : g.C.setTimeout(a, b || 0)
}
g.D函数看起来特别有趣:它似乎是用第一个参数 a 调用的。 ,这大概是一个函数。看起来它可能会调用 bind在引擎盖下。当我要求控制台检查它时,我得到了这个:
> String(g.D)
"function(a,b,c){return a.call.apply(a.bind,arguments)}"
所以虽然这个过程有点复杂,但我们可以清楚地看到这确实发生了。

关于javascript - 为什么 function.toString() 输出 "[native code]",而登录到控制台直接显示函数的源代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68485652/

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