为何两段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"
问题根源
this指向错误:调用sayName时传入的this.name,这里的this并不指向player1或player2实例——在全局作用域下直接调用函数时,this默认指向全局对象(浏览器环境是window,Node.js环境是globalThis)。如果全局对象的name属性恰好是"steve",那不管哪个实例调用,传的都是这个全局值。- 参数遮蔽作用域:
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
相关产品推荐
相关产品推荐

