显式绑定call能有效防御原型链污染对内置方法的劫持,因其绕过原型查找直接调用原生方法;最需防护的是object.prototype.tostring、number.prototype.tofixed等易被污染的实例方法,应统一用call显式调用。

直接用 call 显式绑定 this,能有效切断原型链污染对内置方法行为的劫持路径——因为被污染的原型方法无法通过隐式调用篡改原生逻辑,而显式调用绕过了原型查找过程。
为什么原型链污染会影响内置方法?
攻击者若污染 Object.prototype(如添加或覆盖 toString、valueOf 等),当代码以隐式方式调用这些方法(如 obj.toString())时,JS 引擎会沿原型链查找,最终可能执行被篡改的恶意版本。但若始终用 Function.prototype.call 显式指定 this 为原生构造器实例(如 {}.toString.call(obj)),就跳过了原型链查找,强制使用原始方法。
哪些内置方法最需显式绑定?
以下方法常被污染利用,调用时应优先使用 call:
-
Object.prototype.toString→ 改写为Object.prototype.toString.call(value) -
Array.isArray→ 实际是静态方法,但若担心 polyfill 被污染,可用Array.isArray.call(null, value)(虽非必需,但更稳妥) -
JSON.stringify和JSON.parse→ 本身不依赖this,但若封装了带this上下文的工具函数,需确保内部调用不依赖隐式绑定 -
Number.prototype.toFixed、String.prototype.trim等实例方法 → 统一用Number.prototype.toFixed.call(num, digits)替代num.toFixed(digits)
如何安全封装常用方法?
避免在工具函数中直接引用可能被污染的原型方法:
- 不推荐:
const safeToString = obj => obj.toString();(隐式调用,易被劫持) - 推荐:
const safeToString = obj => Object.prototype.toString.call(obj);(锁定原生实现) - 可预先缓存原生方法:
const nativeToString = Object.prototype.toString;,后续统一用nativeToString.call(obj) - 对高频使用的数组方法,也可缓存:
const nativePush = Array.prototype.push;,再用nativePush.call(arr, item)
注意边界:call 不能解决所有污染问题
call 只能防护「依赖 this 绑定且可通过原型链劫持的方法」。它不防:
- 全局变量污染(如覆盖
JSON对象本身) - 构造函数重定义(如
Array = maliciousArray) - 非原型方法的直接赋值污染(如
Object.assign = maliciousAssign) - ES6+ 的静态方法污染(如
Object.keys = maliciousKeys)——这类需单独冻结或替换引用
所以显式绑定是纵深防御的一环,还需配合 Object.freeze(Object.prototype)、使用 Object.create(null) 创建纯净对象、启用 CSP 等措施。











