You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何两段JavaScript Player代码执行结果不符?name返回异常解析

两段Player构造函数的作用域差异解析

先把你提到的两段代码还原出来,方便对照分析:

第一段(问题代码)

function Player(name) {
  this.name = name;
  this.sayName = function(name) {
    console.log(name);
  };
}

const player1 = new Player("steve");
const player2 = new Player("alice");

player1.sayName(this.name); // 输出"steve"
player2.sayName(this.name); // 也输出"steve"

问题根源

  1. this指向错误:调用sayName时传入的this.name,这里的this并不指向player1或player2实例——在全局作用域下直接调用函数时,this默认指向全局对象(浏览器环境是window,Node.js环境是globalThis)。如果全局对象的name属性恰好是"steve",那不管哪个实例调用,传的都是这个全局值。
  2. 参数遮蔽作用域:sayName函数自己定义了name参数,这个参数会遮蔽外部作用域的同名变量(包括构造函数的name参数、实例的this.name),所以就算你想传实例的name,也得写成player1.sayName(player1.name),而不是依赖全局的this。

第二段(正确代码)

function Player(name) {
  this.name = name;
  this.sayName = function() {
    console.log(name);
  };
}

const player1 = new Player("steve");
const player2 = new Player("alice");

player1.sayName(); // 输出"steve"
player2.sayName(); // 输出"alice"

正确原因:闭包保留构造函数的作用域

当你用new Player()创建实例时,每个构造函数调用都会生成一个独立的执行上下文,里面的name参数是当前实例对应的传入值。而sayName作为构造函数内部定义的函数,会形成闭包——它会保留对构造函数执行上下文的引用,所以每个实例的sayName都能访问到属于自己的那个name参数,自然能输出正确的名字。

补充:更常用的规范写法

还有一种更符合直觉的写法,直接用实例的this.name,效果完全一致:

function Player(name) {
  this.name = name;
  this.sayName = function() {
    console.log(this.name);
  };
}

这里调用player1.sayName()时,this会自动指向调用它的实例player1,所以能拿到正确的name属性。

内容的提问来源于stack exchange,提问作者Bodi Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:17:15