ES6静态方法与非静态方法对比及ES5 OOP写法疑问
Great question! Let's unpack this step by step, including how it ties to ES6's static and instance methods to clear up all your confusion.
1. Your Prototype Method: Correct, It's the Best Practice
Yes, your Person.prototype.whatEver implementation is the standard, best-practice way to define instance methods in ES5—here's why:
- Every instance created with
new Person()shares the exact same reference to this method. No duplicate function copies are stored in each instance, which saves memory (critical if you create many instances). - Inside the method,
thisautomatically refers to the instance that called it, so you can access instance-specific properties likefirstNameandlastNameseamlessly:const bob = new Person("Bob", "Jones"); bob.whatEver(); // Returns "Bob Jones"
2. Your Constructor-Mounted Method: Not a "Bad Practice"—It's ES5's Static Method
Your understanding here has a small key mistake: this method is not included in every instance! This is actually the ES5 equivalent of an ES6 static method.
Let's clarify the facts:
- This method is attached directly to the
Personconstructor function (the "class" itself in ES5 terms), not to its prototype. That means instances likebobcan't call it directly—bob.whatEver()will throw an error. - It doesn't take up memory per instance because it doesn't belong to instances at all; it lives on the constructor object.
- The
thisinside this method refers to thePersonconstructor itself, not an instance. So you can't accessthis.firstNamehere (sincePersondoesn't have that property), but it's perfect for class-level logic, like creating utility functions for the "Person" type:Person.createGuest = function() { return new Person("Guest", "User"); }; // Call it directly on the constructor: const guest = Person.createGuest();
The "bad practice" people might refer to is defining methods inside the constructor like this:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; // ❌ This creates a new function for every instance—wastes memory! this.whatEver = function() { return `${this.firstName} ${this.lastName}`; }; }
That's the pattern to avoid, not the constructor-mounted method you wrote.
3. How This Maps to ES6 Static/Instance Methods
ES6 classes are just syntactic sugar over ES5's prototype system, so the mapping is straightforward:
- ES5 prototype method → ES6 instance method:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } // Instance method (same as Person.prototype.whatEver) whatEver() { return `${this.firstName} ${this.lastName}`; } } - ES5 constructor-mounted method → ES6 static method:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } // Static method (same as Person.createGuest above) static createGuest() { return new Person("Guest", "User"); } }
Quick Recap
- Instance/Prototype Methods: Belong to individual instances, shared across all instances,
thispoints to the instance. Use these for logic that depends on instance data. - Static/Constructor-Mounted Methods: Belong to the "class" (constructor) itself, not instances,
thispoints to the class. Use these for utility logic related to the class as a whole—they're not bad practice at all when used appropriately!
内容的提问来源于stack exchange,提问作者danedidug

