call实现函数借用本质是利用显式绑定临时改变this指向,使方法在目标对象上执行而不修改原型;关键在于方法不依赖特定对象、目标具备对应结构、用call设置this并传参。

call 实现函数借用,本质是利用 JavaScript 中函数的显式绑定机制,把一个对象的方法“临时借给”另一个对象使用,不修改原型、不建立继承关系,只改一次 this 指向。
关键就三点:
- 方法本身不依赖特定对象(比如
Array.prototype.slice只读取this.length和this[0]、this[1]…) - 目标对象具备对应结构(如类数组对象有数字索引 +
length属性) - 用
call把目标对象设为方法执行时的this,再传入参数
借用数组方法处理类数组对象
类数组对象(如 arguments、NodeList、HTMLCollection)没有 slice、forEach 等方法,但它们有 0、1、length 这样的属性。只要让 Array.prototype 上的方法在它上面运行,就能正常工作。
-
把
arguments转成真数组function foo() { const args = Array.prototype.slice.call(arguments); // 或简写为: const args = [].slice.call(arguments); } -
遍历 DOM 节点列表(不转数组,直接操作)
const divs = document.querySelectorAll('div'); Array.prototype.forEach.call(divs, el => { el.style.color = 'red'; }); -
向类数组对象添加元素(需
length可写)const arrLike = { 0: 'a', 1: 'b', length: 2 }; Array.prototype.push.call(arrLike, 'c', 'd'); // 结果:{0:'a', 1:'b', 2:'c', 3:'d', length:4}
借用其他内置对象的方法
不只是数组,任何原型上的方法都能借:
-
判断类型(绕过重写的
toString)Object.prototype.toString.call([]); // "[object Array]" Object.prototype.toString.call(null); // "[object Null]" Object.prototype.toString.call(/a/g); // "[object RegExp]"
-
字符串借用数组方法(自动包装,只读)
[].join.call('hello', '-'); // "h-e-l-l-o" [].filter.call('hello', c => c > 'c').join(''); // "llo" // 注意:push/pop 会失败,字符串不可变
安全封装与复用建议
避免每次重复写 Array.prototype.xxx.call,可封装成工具函数:
-
通用转换函数(无副作用)
const toArray = obj => Array.prototype.slice.call(obj); toArray(document.querySelectorAll('p')); // → 真数组 -
绑定后复用(适合高频调用)
const forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); forEach(els, handler);
-
构造器借用(模拟继承式初始化)
function Child(name) { Parent.call(this, name); // 借用父构造逻辑 }
核心不是“复制方法”,而是“换 this 执行”。只要目标对象满足方法内部的数据访问约定(比如有 length、能用 [n] 取值),借用就能成立。现代代码中虽可用 Array.from 或展开运算符替代部分场景,但 call 借用依然轻量、兼容、可控。


















