类中函数声明与函数表达式的引用差异、使用范围及实例化问询
Great question! It’s smart to dig into how these two patterns differ in class contexts—even if you know basic function declarations vs. expressions, their behavior inside classes shifts in important ways. Let’s break down your two examples step by step.
1. 写法1: Prototype Method (class xyz { someFunction(){ ... } })
This defines a prototype method: the function is attached to xyz.prototype, meaning every instance of xyz shares the same function reference.
Where someFunction works inside the class:
- Inside the
constructor: You can call it viathis.someFunction()at any point in the constructor. Since prototype methods exist as soon as the class is defined, the instance’s prototype chain already points to this function when the constructor runs.class xyz { constructor() { this.someFunction(); // Works perfectly—logs "Hello!" } someFunction() { console.log("Hello!"); } } - Inside other prototype methods: Use
this.someFunction()to call it. Again, the prototype chain ensuresthisresolves to the instance, which can access the shared prototype method. - What doesn’t work: You can’t call
someFunction()directly in the class’s top-level scope (outside methods/constructor). The class body doesn’t expose method names as variables—you need to reference them viathisorxyz.prototype.
Instantiation timing:
Class declarations are hoisted but exist in a "temporal dead zone" (like let/const). This means you can’t instantiate xyz before the class is declared, but you can instantiate it anywhere after the declaration.
// new xyz(); // Error: Cannot access 'xyz' before initialization class xyz { /* ... */ } new xyz(); // Works fine
2. 写法2: Instance Property Function (class xyz { someFunction = function(){ ... } })
This defines an instance property: the function is created and assigned to each individual instance when the instance is initialized (not shared on the prototype). Note: Using var here is redundant in modern class syntax—you can just write someFunction = function(){};.
Where someFunction works inside the class:
- Inside the
constructor—but only after the property is initialized: Class instance properties are initialized in the order they’re written, right aftersuper()(if extending another class) and before the rest of the constructor runs. If you callthis.someFunction()before the property is declared, you’ll get an error:
Fix this by calling it after the property, or reordering the property above the constructor:class xyz { constructor() { this.someFunction(); // Error: this.someFunction is not a function } someFunction = function() { console.log("Hello!"); } }class xyz { someFunction = function() { console.log("Hello!"); } constructor() { this.someFunction(); // Works now } } - Inside other instance methods: You can safely call
this.someFunction()here, because by the time the method runs, the instance has already been initialized and the property exists.
Instantiation timing:
Same as the prototype method pattern—you can only instantiate xyz after the class is declared (due to the temporal dead zone). The key difference is that each instance gets its own copy of someFunction, rather than sharing a single prototype method.
Quick Summary of Core Differences
- Mounting Location: Prototype methods (写法1) live on
xyz.prototype(shared by all instances); instance property functions (写法2) are unique to each instance. - Constructor Access: Prototype methods are available immediately in the constructor; instance property functions are only accessible after their declaration in the class body.
- Memory & Performance: Prototype methods are more memory-efficient (one shared function); instance property functions use more memory (each instance has its own copy).
thisBinding: For prototype methods,thisis dynamically bound (depends on how the function is called). For instance property functions, if you use an arrow function (someFunction = () => {}),thisis permanently bound to the instance (avoids binding issues in callbacks).
内容的提问来源于stack exchange,提问作者void

