
本文详解如何从零手写 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 <h3>为什么你的原始代码不通过测试?</h3><p>你当前的实现存在三个核心问题:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java"><img
src="https://img.php.cn/upload/skill/000/000/081/178955835420587.jpg" alt="Alibabacloud Sdk Client Initialization For Java" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="overflowclass">Alibabacloud Sdk Client Initialization For Java</a>
<p class="overflowclass">在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。</p>
</div>
<a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><ol>
<li><p><strong>this 绑定错误</strong><br>
你将方法直接赋值给 source.push2,导致 this 指向 source —— 这看似可行,但一旦方法被复用(如 anotherArray.push2 = source.push2),this 仍指向 source,造成逻辑错乱。正确方式是让方法始终作用于<strong>调用它的数组实例</strong>,因此必须定义在 Array.prototype 上。</p></li>
<li><p><strong>未挂载到原型链</strong><br>
若未在 Array.prototype 上定义,其他数组实例无法访问该方法(如 [] .push2() 会报错)。只有挂载到原型,才能保证所有数组实例继承该能力。</p></li>
<li><p><strong>返回值不符合规范</strong><br>
原生 push() 返回的是数字类型的<strong>新长度</strong>(如 [1,2].push(3) 返回 3),而你的代码返回了数组本身(return source),导致断言失败(如 expect(...).toEqual([...]) 期望数组,但测试框架实际校验的是 push 的返回值或副作用)。</p></li>
</ol><h3>使用示例与验证</h3><pre class="brush:php;toolbar:false;">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 测试用例:
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)打下坚实基础。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










