在类内部和外部定义JavaScript函数的区别

20

我正在尝试弄清楚在JavaScript中在类内部或外部定义函数是否有任何区别。为什么我会选择一种方式而不是另一种方式?(请注意我的getName [在类内部]和getName2 [在类外部])。

class TestClass {
    constructor(myName) {
        this.name = myName;
    }

    getName() {
        return this.name;
    }
}

TestClass.getName2 = function() {
    //won't actually print the name variable set since not associated with an instance of the class?
    console.log(this.name);
};

var test = new TestClass("Joe");

console.log(test.getName());

///////////////

TestClass.getName2();

输出:

Joe
TestClass

我在测试中所看到的唯一区别是,我无法在我的getName2中访问this.name,因为我认为它与TestClass的任何实例都没有关联。因此,我的getName2几乎就像一个静态类函数,它与类的实例无关。请帮助我澄清这一点,并解释为什么我会选择以一种方式实现函数而不是另一种方式。
3个回答

23

根据MDN文档:

在ECMAScript 2015中引入的JavaScript类,主要是对JavaScript现有基于原型的继承的语法糖。类语法并不会向JavaScript引入新的面向对象继承模型。

因此,这个...

class TestClass {
  constructor(myName) {
    this.name = myName;
  }

  getName() {
    return this.name;
  }

  static getName2() {
    return 'getName2 result';
  }
}

...与此完全等同:

const TestClass = function(myName) {
  this.name = myName;
}

TestClass.prototype.getName = function() {
  return this.name;
}

TestClass.getName2 = function() {
  return 'getName2 result';
}
所以,无论您使用旧的原型语法还是较新的ES6 class 语法只是个人偏好问题,正如您所怀疑的那样,在一个class上直接定义方法与创建一个static类方法完全相同。

0
我注意到的一件事是,您正在使用保留关键字来定义对象、属性和方法。TestClass.getName2() 应该返回 undefined,但由于您使用了 "name" 保留关键字,它返回了类的名称,这被视为一个类似函数的对象。在您的情况下,您正在使用 this.name,它指的是类名,并返回 "TestClass"。
示例:

class TestClass {
    constructor(userName) {
        this._userName = userName;
    }

    getName() {
        return this._userName;
    }
}

TestClass.getName2 = function() {
    // returns undefined now
    console.log(this._userName);
};

var test = new TestClass("Joe");

console.log(test.getName()); // returns Joe

///////////////

TestClass.getName2(); // returns undefined
let testClassName = TestClass.name; // Just a little proof of what is returned below
console.log(testClassName); // returns TestClass

我的唯一建议是,你应该紧跟当前的保留关键字以及它们可以和不能使用的地方。你也可以专注于你代码中的命名规范。


0

我认为你永远不会有任何理由这样做

TestClass.getName2 = function() {

如果你想要一个独立的函数,那就把它写成一个独立的函数。

例如:

export function getName2() {...};
export TestClass;

如果你想扩展一个已有的类,你需要这样做:
TestClass.prototype.getName2 = function() {

这将允许您访问此内容。


1
进行...的原因是:作用域getName2 =在其所在的作用域中创建一个变量。TestClass.getName2 =创建一个由TestClass限定的变量。尽可能地,将变量限制在适当的上下文中是很好的。这可以最小化"命名空间污染"。并且表明getName2可能正在访问或设置与TestClass有关但不是单个TestClass实例的值。也许是应该影响所有TestClass实例的"配置设置"。 - ToolmakerSteve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接