
本文详解如何从零手写 push 方法:需正确绑定 this、挂载到 array.prototype、返回新长度而非数组本身,并避免使用 push、concat 等原生数组方法。
本文详解如何从零手写 push 方法:需正确绑定 this、挂载到 array.prototype、返回新长度而非数组本身,并避免使用 push、concat 等原生数组方法。
在 JavaScript 中,Array.prototype.push() 用于向数组末尾添加一个或多个元素,并返回修改后数组的新长度。若需手动实现该行为(例如在算法训练、面试题或教学场景中),必须严格遵循其规范:
- 操作目标为调用者自身(即 this 引用的数组);
- 支持传入任意数量的参数;
- 直接修改原数组(非创建新数组);
- 返回值必须是操作后数组的 length,而非数组本身;
- 不得使用任何内置数组方法(如 push, concat, splice, unshift 等)。
以下是符合全部要求的手写 push2 实现:
// ✅ 正确做法:将方法挂载到 Array.prototype
Array.prototype.push2 = function(...items) {
// 遍历所有传入参数,逐个赋值到数组末尾
for (let i = 0; i < items.length; i++) {
this[this.length] = items[i];
}
// ⚠️ 关键:返回修改后的 length,而非 this
return this.length;
};为什么你的原始代码不通过测试?
你当前的实现存在三个核心问题:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
this 绑定错误
你将方法直接赋值给 source.push2,导致 this 指向 source —— 这看似可行,但一旦方法被复用(如 anotherArray.push2 = source.push2),this 仍指向 source,造成逻辑错乱。正确方式是让方法始终作用于调用它的数组实例,因此必须定义在 Array.prototype 上。未挂载到原型链
若未在 Array.prototype 上定义,其他数组实例无法访问该方法(如 [] .push2() 会报错)。只有挂载到原型,才能保证所有数组实例继承该能力。返回值不符合规范
原生 push() 返回的是数字类型的新长度(如 [1,2].push(3) 返回 3),而你的代码返回了数组本身(return source),导致断言失败(如 expect(...).toEqual([...]) 期望数组,但测试框架实际校验的是 push 的返回值或副作用)。
使用示例与验证
const arr = [1, 2, 3]; const result = arr.push2(72, 12, 41); console.log(arr); // [1, 2, 3, 72, 12, 41] ✅ 原数组被修改 console.log(result); // 6 ✅ 返回新长度
配合 Jest 测试用例:
立即学习“Java免费学习笔记(深入)”;
it('Push method should work with many items', () => {
const source = [1, 2, 3];
const result = source.push2(72, 12, 41);
expect(source).toEqual([1, 2, 3, 72, 12, 41]); // ✅ 验证数组内容
expect(result).toBe(6); // ✅ 验证返回值为 length
});注意事项
- ❌ 不要使用 this.concat(items) 或 this.push(...items) —— 违反“不使用数组方法”的前提;
- ✅ 利用 this.length 动态获取末尾索引并赋值,是最基础、最符合底层原理的方式;
- ✅ 支持 rest 参数(...items)天然兼容多参数,无需 arguments;
- ⚠️ 在生产环境请勿覆盖 Array.prototype —— 可能引发兼容性或第三方库冲突;本实现仅用于学习与测试目的。
掌握这一实现,不仅加深对 this、原型链和数组底层机制的理解,也为实现其他数组方法(如 pop、unshift)打下坚实基础。

















