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

为何在JavaScript类构造函数内无法指定函数参数名?

JavaScript构造函数内带参数名调用方法报错的原因与解决

问题重现

先定义如下类:

class Person {
    constructor(name, age) {
        this.name = name,
        this.age = age
    }

    addYear() {
        this.age++;
    }

    changeName(newName) {
        this.name = newName;
    }

    changeAge(newAge) {
        this.age = newAge;
    }

    changeAgeAndName(newName, newAge) {
        this.changeName(newName=newName);
        this.changeAge(newAge=newAge);
    }
}

在类外部调用方法时,带参数名的写法能正常运行:

let p1 = new Person('George', 20);
console.log(p1); // Person { name: 'George', age: 20 }

p1.changeName(newName='Robert');
console.log(p1); // Person { name: 'Robert', age: 20 }

p1.changeAgeAndName(newName='Joe', newAge=23);
console.log(p1); // Person { name: 'Joe', age: 23 }

但在构造函数内使用同样写法调用changeAgeAndName时,会抛出错误:

class Person {
    constructor(name, age) {
        this.changeAgeAndName(newName=name, newAge=age); // 报错:ReferenceError: newName is not defined
    }
    // 其他方法同上
}

去掉参数名直接传值则正常运行:

class Person {
    constructor(name, age) {
        this.changeAgeAndName(name, age); // 正常执行
    }
    // 其他方法同上
}

let p2 = new Person('Mike', 40);
console.log(p2); // Person { name: 'Mike', age: 40 }

原因分析

JavaScript根本没有「命名参数」这种语法,你之前写的newName='Robert'其实是赋值操作,不是指定参数名:

  • 在类外部的普通代码里,非严格模式下给未声明的变量赋值会偷偷创建全局变量,所以不会报错,但这纯属巧合——因为你赋值的变量名刚好和方法参数名一致,而且传参顺序也对,所以结果看起来是对的。
  • 但类的构造函数默认运行在严格模式下,严格模式禁止这种隐式创建全局变量的操作。当你在构造函数里写newName=name时,JS会寻找newName这个变量,但你从未声明过它,直接就抛出ReferenceError了。

正确实现方式

如果想明确参数含义,给你两个靠谱的实现方式:

方案1:使用对象解构参数

把方法改成接受一个对象参数,通过解构获取值,调用时传入键值对对象,实现类似命名参数的效果:

class Person {
    constructor(name, age) {
        this.changeAgeAndName({ newName: name, newAge: age });
    }

    changeName(newName) {
        this.name = newName;
    }

    changeAge(newAge) {
        this.age = newAge;
    }

    changeAgeAndName({ newName, newAge }) { // 对象解构获取参数
        this.changeName(newName);
        this.changeAge(newAge);
    }
}

let p3 = new Person('Alice', 25);
console.log(p3); // Person { name: 'Alice', age: 25 }

// 外部调用时也能明确传参含义
p3.changeAgeAndName({ newName: 'Luna', newAge: 30 });
console.log(p3); // Person { name: 'Luna', age: 30 }

方案2:保留顺序+注释说明

如果不想修改方法参数结构,可以在调用时添加注释明确参数含义:

class Person {
    constructor(name, age) {
        // 对应参数:newName=name, newAge=age
        this.changeAgeAndName(name, age);
    }
    // 其他方法同上
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:10:32