PAYATHON 2026

这个 JavaScript class 示例适合作为新的 placeholder 吗?

技术老齐

这段代码可以作为练习起点,用来介绍 class 前建议做些修改。它展示了类的声明、构造函数和方法调用,但 join() 没有用到构造函数保存的数据,读者不容易看出实例属性与方法之间的关系。

如果这里的 placeholder 指教学用的占位示例,可以根据讲解目标自行设计。foo、bar 或 a、b 都只是示例名称。介绍类时,选用含义明确的名称,更方便解释对象代表什么。

原示例有哪些问题?

实例保存的数据没有参与后续操作:

const ball = new test("Dog", "Cat");

ball.join(["Hello", "World!"]); // 返回 "Hello World!"

"Dog" 和 "Cat" 分别保存在 ball.a、ball.b 中,join() 却只处理传入的数组。换一个实例,只要传入相同数组,结果就一样。当前的 join() 用普通函数也能实现,因此这个例子没能充分说明创建实例的用途。

数组检查也增加了学习负担。初学者需要同时理解 Array.isArray()、every()、箭头函数和 typeof,容易把注意力放在参数校验上。

命名也可以更清楚。class test 的语法合法,不过类名通常采用 PascalCase,例如 Greeting。ball、a、b 这些名称与字符串拼接的用途没有明显联系,读者很难从名称理解它们的含义。

怎样改成更清楚的 class 入门示例?

可以保留拼接两个字符串的功能,做以下调整:

  1. 给类和属性取有含义的名称。
  2. 在构造函数中保存每个实例的数据。
  3. 让方法读取这些属性,并展示不同实例的结果。
class Greeting {
  constructor(first = "Hello", second = "World!") {
    this.first = first;
    this.second = second;
  }

  join() {
    return [this.first, this.second].join(" ");
  }
}

const greeting = new Greeting();
const animalGreeting = new Greeting("Dog", "Cat");

console.log(greeting.join());       // "Hello World!"
console.log(animalGreeting.join()); // "Dog Cat"

new Greeting(...) 创建实例并调用 constructor,构造函数中的 this 指向正在初始化的实例。调用 greeting.join() 时,方法通过 this.first 和 this.second 读取该实例的数据。两个实例保存的属性值不同,调用同一个方法会得到不同的结果,实例属性和实例方法的用途也就更容易理解。

这里的接口也发生了变化:join() 拼接的是实例中保存的数据,不再接收待拼接的数组。

默认值和输入校验需要注意什么?

原代码中的写法:

this.a = a || "Hello";

会在 a 为假值时使用 "Hello",包括 ""、0、false、null、undefined 和 NaN。如果允许输入空字符串,这种写法会意外地将它替换掉。

改进后的示例使用默认参数:

constructor(first = "Hello", second = "World!")

只有省略对应实参,或显式传入 undefined 时,默认参数才会生效。传入 "" 或 null 都不会触发默认值。默认参数也不负责类型校验,这个入门示例假定调用者传入字符串。

后续讲到参数校验时,可以单独扩展示例,说明如何处理无效输入。原代码对非数组、包含非字符串元素的数组,以及合法的空数组都返回 "",调用者无法仅凭返回结果区分这些情况。基础教学中,先讲清楚实例数据与方法的关系,再加入校验规则,会更容易理解。

备注:内容仅供参考。