最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ecmascript 6 - Is there a difference between extending Object vs not extending at all in javascript? - Stack Overflow

programmeradmin0浏览0评论

I found out that I can extend Object like this:

class MyObject extends Object {}

Is there any difference with this and not extending at all, like this:

class MyObject {}

The reason I ask this is because I have the following mixin:

const MapMixin = (Base = Object) => class extends Base {
  static from(array) {
    return new this(Object.assign(...array.map(([key, value]) => ({[key]: value}))));
  }

  map(...args) {
    return this.constructor.from(this.entries().map(...args));
  }

  entries() {
    return Object.entries(this);
  }
};

This mixin could be used like this:

class MyObject extends MapMixin(MyBaseClass) {}

But if there is no base class, I now have specified that it then extends Object as default:

class MyObject extends MapMixin() {}

So I'm wondering, if this practically works the same as not extending anything at all.

I found out that I can extend Object like this:

class MyObject extends Object {}

Is there any difference with this and not extending at all, like this:

class MyObject {}

The reason I ask this is because I have the following mixin:

const MapMixin = (Base = Object) => class extends Base {
  static from(array) {
    return new this(Object.assign(...array.map(([key, value]) => ({[key]: value}))));
  }

  map(...args) {
    return this.constructor.from(this.entries().map(...args));
  }

  entries() {
    return Object.entries(this);
  }
};

This mixin could be used like this:

class MyObject extends MapMixin(MyBaseClass) {}

But if there is no base class, I now have specified that it then extends Object as default:

class MyObject extends MapMixin() {}

So I'm wondering, if this practically works the same as not extending anything at all.

Share Improve this question asked Oct 17, 2017 at 8:59 KasperKasper 13.6k15 gold badges43 silver badges63 bronze badges 6
  • Aren't all Object's prototypes Object by default? (unless you use Object.create(null)) --- Update... it seems not. – evolutionxbox Commented Oct 17, 2017 at 9:07
  • On the other hand, why are you extending at all? – evolutionxbox Commented Oct 17, 2017 at 9:08
  • 1 @evolutionxbox After experimenting a bit, there seems to be some differences. Try logging (class extends Object{}).freeze vs (class {}).freeze. – Kasper Commented Oct 17, 2017 at 9:24
  • Why extend? Why bother with classical inheritance at all? – evolutionxbox Commented Oct 17, 2017 at 9:27
  • If I wanted to use the Object freeze method? Object.freeze(MyObject). – evolutionxbox Commented Oct 17, 2017 at 9:59
 |  Show 1 more ment

3 Answers 3

Reset to default 6

I don't know if it's clear from the other answers here, but the difference is in the static inheritance.

Prior to the class keyword, inheritance in JavaScript has been very focused on instance inheritance. No one (that I've seen) cared to go through the trouble of having one class/constructor inherit static members from the super class/constructor. Not to mention the only way to do this was through the non-standard __proto__ property.

So when we look at a class extending another class today, we think about how inheritance works between instances of that class. For instances, extending Object, or nothing at all, is the same because instances will inherently inherit from Object as a base.

class A {}
class B extends Object {}

let a = new A()
let b = new B()

// a.__proto__.__proto__ === b.__proto__.__proto__ === Object.prototype 

But it may not be clear, or well understood that the extends keyword is doing more than just setting up inheritance for instances. It also sets up inheritance between the class constructors. So for B above, the use of extends also means a Object.setPrototypeOf(B, Object) getting called in the background for B. So, for example:

class A {} // A constructor inherits nothing (is a basic Function type)
class B extends Object {} // B inherits from Object

// A.setPrototypeOf === undefined
// B.setPrototypeOf === Object.setPrototypeOf

B, extending Object, inherits all the static methods from Object, whereas A not extending anything, doesn't.

The difference is between B.prototype (or B.prototype.__proto__) - what instances inherit from, and B.__proto__ - what the class constructor inherits from. Extending Object or not does not affect the prototype or what the instances inherit from, but it does affect the class's __proto__, or static inheritance.

There's a subtle difference.

If you declare classes A, B and create instances like this:

class A {}
class B extends Object {}

let a = new A()
let b = new B()

A is a base class, and B is a derived class.

As a result, a is allocated directly from A but b is allocated from Object.
So you can find their prototypes:

console.log(A.__proto__) // [Function]          (Function.prototype)
console.log(B.__proto__) // [Function: Object]  (Object)

via http://2ality./2015/02/es6-classes-final.html#the-extends-clause.

As Shu Ding said, the prototype chain differs

To be more explicit:

const getNProtos = (n, { __proto__:p }={}, protos=[]) => n && p ? getNProtos(n-1, p, [ ...protos, p ]) : [ ...protos, p ]

[ 
  class extends Object{}, 
  class extends (class {}){}, 
  class {} 
].map(obj => getNProtos(3, obj)
  .forEach(x => x.forEach(y => console.log(y)) || console.log('\n'))
)

ƒ Object() { [native code] }
ƒ () { [native code] }
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
null


class {}
ƒ () { [native code] }
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
null


ƒ () { [native code] }
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
null

The prototype chains are almost identical, with the derived class simply having an extra one (the Object constructor) atop the chain. Extending with Object looks similar to extending with a plain class {}, except of course that Object has its own methods available.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论