☰
现代 JavaScript 教程:数组下标调用函数时 `this` 指向哪里?——`arr[2]()` 背后的对象方法调用机制
2026/10/6 1:53:59 网站建设 项目流程
  • 文档
  • 教程
  • 前端

【免费下载链接】zh.javascript.info

现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。

项目地址:https://gitcode.com/gh_mirrors/zh/zh.javascript.info
点击查看免费下载

数组(Array)是 JavaScript 中最常用的有序集合,但它的本质仍然是对象:arr[0]与obj[key]是同一种语法。当数组中存放的是函数,并通过arr[2]()这样的下标语法调用时,this究竟指向谁?本文以现代 JavaScript 教程中的一道经典习题("在数组上下文调用")为骨架,结合仓库中「数组」「对象方法与 this」「Reference Type」等章节的源码级原理,彻底讲清数组元素调用函数的this绑定规则,帮助你建立"函数调用方式决定this"的清晰认知。

题目:结果是什么?为什么?

这道题出自 1-js/05-data-types/04-array/3-call-array-this/task.md,重要性标记为 5(importance: 5),是数组章节中一道高频易错的思维题:

let arr = ["a", "b"]; arr.push(function() { alert( this ); }); arr[2](); // ?

先别急着运行,想一想:arr[2]取出来的是一个函数,再紧跟()调用它。此时函数内部的this是什么?alert(this)会弹出什么内容?

标准答案:this指向数组本身

答案在 solution.md 中给出了非常精炼的解释:

arr[2]()调用从句法来看可以类比于obj[method](),与obj对应的是arr,与method对应的是2。

也就是说,arr[2]()本质上就是"从对象arr上取出名为2的属性(一个函数),并以对象方法的方式调用它"。因此它接收this引用的对象就是arr,alert(this)会输出整个数组:

let arr = ["a", "b"]; arr.push(function() { alert( this ); }) arr[2](); // a,b,function(){...}

调用后arr一共有 3 个元素:最开始的两个字符串"a"、"b",再加上后来通过push添加进来的一个函数。所以this的字符串化结果就是由逗号连接的"a,b,function(){...}"。

为什么arr[2]()等价于obj[method]()?

数组是"特殊对象",下标访问本质是属性访问

要理解上面这个结论,必须回到数组的本质。在 1-js/05-data-types/04-array/article.md 的「内部」一节明确写道:

数组是一种特殊的对象。使用方括号来访问属性arr[0]实际上是来自于对象的语法。它其实与obj[key]相同,其中arr是对象,而数字用作键(key)。

也就是说,arr[2]中的数字下标2,对 JavaScript 引擎而言就是一个普通的属性键(key)。这一点在数组章节中其实早有铺垫——数组可以存储任何类型的元素,包括函数:

// 混合值 let arr = [ 'Apple', { name: 'John' }, true, function() { alert('hello'); } ]; // 获取索引为 3 的函数并执行 arr[3](); // hello

正因为数组元素可以是函数,而数组本身是对象,arr[3]()与arr[2]()就完全落入了"对象方法调用"的范畴。

this的值取决于调用方式,而不是函数定义位置

在 1-js/04-object-basics/04-object-methods/article.md 的「方法中的 this」一节中,教程给出了最核心的规则:

this的值就是在点之前的这个对象,即调用该方法的对象。

更一般地,这一章还强调了一个容易被其他语言背景开发者误解的事实:JavaScript 的this是"自由"的,它的值在调用时计算,取决于"点符号前/调用者上下文里"的是什么对象,而不是函数声明在哪里。例如:

let user = { name: "John" }; let admin = { name: "Admin" }; function sayHi() { alert( this.name ); } user.sayHi = sayHi; admin.sayHi = sayHi; user.sayHi(); // John(this == user) admin.sayHi(); // Admin(this == admin)

同一个函数,挂到不同对象上、以不同对象调用,this就不同。回到题目:arr[2]()中函数是以arr为调用者被调用的,this自然就是arr。

深层机制:Reference Type(引用类型)

如果你还想知道"为什么arr[2]()能正确把this传给函数,而let f = arr[2]; f()就不行",那就需要进入高阶主题 1-js/99-js-misc/04-reference-type/article.md 一探究竟。

obj.method()在语法上包含两个操作:

  1. 点'.'(或方括号'[...]')取出属性obj.method的值;
  2. ()立即执行它。

this的信息从第一步传到第二步,靠的是一个语言内部的"规范类型"——Reference Type。它是一个三元组合(base, name, strict):

  • base:来源对象(这里就是arr);
  • name:属性名(这里就是数字2);
  • strict:严格模式下为true。

当()被作用在这个 Reference Type 上时,调用会接收到完整的对象与方法信息,从而把this设置为base(即arr)。这也是为什么只有直接以obj.method()或obj['method']()语法调用时this才被正确传递——方括号与点号在这里作用相同,arr[2]()正是后者。

反过来,一旦把函数取出来赋给变量再调用,Reference Type 会被整体丢弃,只剩下裸函数,this就丢失了:

let f = arr[2]; f(); // this === undefined(严格模式),报错或输出 undefined

这恰好印证了 solution.md 的结论:arr[2]()是"对象方法式调用",而非"独立函数调用"。

延伸思考:这道题教会我们什么?

1. 任何数组元素都可以"变成方法"。只要元素是函数,通过下标调用时它就是该数组的方法,this绑定到数组。这在编写以数组为上下文的小型回调、策略函数时可能造成"意外惊喜"——例如arr[0]()内部的this会是整个数组,而非undefined或全局对象。

2.alert(this)输出数组内容。数组有自己的toString实现,返回以逗号分隔的元素列表(见 数组章节的 toString 一节),所以this(即数组)被alert字符串化后显示为a,b,function(){...}。

3. 丢失this是常见 bug 源头。动态取出函数再调用(let f = obj.m; f()、回调传参、解构赋值等)都会触发 Reference Type 被丢弃,导致this丢失。解决方案包括bind、箭头函数或在调用点保持obj.method()语法——这与题目形成完美对照:同样是数组里的函数,直接arr[2]()与先赋值再调用,结果截然不同。

小结

  • 数组是特殊对象,arr[i]本质是obj[key]形式的属性访问;
  • 数组可存储函数,arr[i]()等价于"以数组为调用者的方法调用",this指向数组本身;
  • 本题中alert(this)输出a,b,function(){...},因为数组被字符串化为逗号分隔的元素列表;
  • 深层原因是 Reference Type 机制:只有obj.method()/obj['method']()直接调用才保留this绑定,拆开赋值即丢失。

如果希望进一步吃透相关原理,建议按顺序阅读仓库中的 数组完整章节、对象方法与 this 以及高阶主题 Reference Type,并结合本题的 task.md 与 solution.md 亲手运行验证。

  • 文档
  • 教程
  • 前端

【免费下载链接】zh.javascript.info

现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。

项目地址:https://gitcode.com/gh_mirrors/zh/zh.javascript.info
点击查看免费下载
上一篇:技术方案:使用ONNX模型实现高效图像标签生成系统
下一篇:ACE-Step UI终极指南:免费开源AI音乐生成工具完整使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询