原型继承:Object.create与Object.assign的差异解析
Great question—this is such a common sticking point when wrapping your head around JavaScript's prototype system, especially after diving into Kyle Simpson's You Don't Know JS (fantastic deep dive, by the way!). Let's break down the key differences between Object.create() and Object.assign() specifically in the context of setting up prototype inheritance like your Foo/Bar example.
First, Recap Our Inheritance Goal
In your code, we want Bar instances to inherit methods from Foo.prototype (like myName). This means we need to link Bar.prototype's internal [[Prototype]] to Foo.prototype—so when a Bar instance looks for a method it doesn't have, it traverses the prototype chain up to Foo.prototype to find it.
What Object.create() Does (The Correct Prototype Link)
The line Bar.prototype = Object.create(Foo.prototype); is exactly the right tool for this job. Here's why:
Object.create(obj)creates a new, empty object whose internal[[Prototype]]is directly set toobj(in this case,Foo.prototype).- This establishes a true prototype chain:
Bar Instance → Bar.prototype → Foo.prototype → Object.prototype. - Any methods or properties added to
Foo.prototypelater will automatically be accessible toBarinstances, because the lookup happens via the prototype chain (not copied properties).
Let's expand the example to see this in action:
function Foo(name) { this.name = name; } Foo.prototype.myName = function () { return this.name; }; function Bar(name, label) { Foo.call(this, name); this.label = label; } // Correct prototype link Bar.prototype = Object.create(Foo.prototype); // Fix the constructor property (optional but good practice) Bar.prototype.constructor = Bar; // Add a method to Foo.prototype later Foo.prototype.greet = function() { return `Hello, ${this.name}!`; }; const bar1 = new Bar("Alice", "A"); bar1.greet(); // Returns "Hello, Alice!" — works because of prototype chain
What Object.assign() Does (Property Copy, Not Inheritance)
Object.assign(target, ...sources) is a tool for copying enumerable own properties from source objects to a target object. It does not modify the target object's prototype chain.
If someone tried to use Object.assign instead of Object.create here, it would look like this:
// Incorrect attempt at "inheritance" with assign function Bar(name, label) { Foo.call(this, name); this.label = label; } // Bar.prototype starts as a default object linked to Object.prototype Object.assign(Bar.prototype, Foo.prototype); const bar2 = new Bar("Bob", "B"); bar2.myName(); // Works — but only because myName was copied to Bar.prototype // Now add a new method to Foo.prototype Foo.prototype.greet = function() { return `Hello, ${this.name}!`; }; bar2.greet(); // TypeError: bar2.greet is not a function — no prototype chain link!
Here, Bar.prototype still has Object.prototype as its prototype. The myName method is just a copy on Bar.prototype, not a delegated lookup. Any new methods added to Foo.prototype won't be available to existing or new Bar instances, because there's no chain to traverse.
Core Differences Summary
Object.create(): Builds a prototype chain. It's for establishing true prototype delegation, which is the foundation of JavaScript's inheritance model. This is exactly what Kyle Simpson recommends in the book for linking prototypes.Object.assign(): Copies properties. It's for merging property values between objects, not for setting up inheritance. It doesn't touch the internal[[Prototype]]of the target object.
Quick Note on Edge Cases
- When using
Object.create, remember to reset theconstructorproperty onBar.prototype(since the new object created byObject.createinheritsFoo's constructor instead of pointing toBar). Object.assignonly copies enumerable own properties—so ifFoo.prototypehas non-enumerable properties, they won't be copied toBar.prototype.
内容的提问来源于stack exchange,提问作者mohsinulhaq

