类数组对象可借用数组方法,因其具备length和数字索引,配合call/apply动态绑定this,使数组方法能正常访问其属性;字符串也可被自动包装后借用,但修改类方法会静默失败;object.prototype.tostring.call则是判断内置类型的最可靠方式。

类数组对象(如 arguments、NodeList、HTMLCollection)有 length 和数字索引,但没有数组方法。原型方法借用就是让它们“临时使用”数组原型上的方法,不转换结构、不创建新数组,直接操作原对象。
为什么能借用?
关键在于 JavaScript 的函数调用机制和 this 的动态绑定:
- 数组方法(如
slice、forEach、push)内部只依赖this.length和this[0]、this[1]这类访问模式 - 只要传入的对象具备数值索引 +
length属性,这些方法就能正常运行 -
call或apply可把任意对象设为方法执行时的this,从而“骗过”方法体内的逻辑
常用借用方式与写法
以下写法本质相同,推荐用更清晰的 Array.prototype.xxx.call 形式:
-
Array.prototype.forEach.call(list, callback)—— 遍历不生成新数组 -
Array.prototype.slice.call(arguments)—— 转成真数组(兼容老环境) -
[].forEach.call(nodelist, fn)—— 简写,但易误解为创建空数组再调用 -
Array.prototype.pop.call(obj)—— 直接修改原类数组对象(需有可写的length)
字符串也能借用数组方法
字符串虽是原始类型,但在方法借用中会被自动包装为类数组形式:
[].join.call('hello', '-') → 'h-e-l-l-o'[].filter.call('hello', c => 'aeiou'.includes(c)).join('') → 'eo'- 注意:字符串是只读的,
pop、push类修改方法会静默失败或报错
类型判断中的经典借用
借用 Object.prototype.toString 是最典型的非数组场景:
Object.prototype.toString.call([]) → '[object Array]'Object.prototype.toString.call(null) → '[object Null]'- 它绕过了对象自身重写的
toString(),直接调用原型上最原始的实现 - 这是判断内置类型最可靠的方式,比
typeof更精确











