【问题标题】:In ES6 class syntax why setPrototypeOf() work and other similar method don't在 ES6 类语法中为什么 setPrototypeOf() 工作而其他类似方法不工作
【发布时间】:2019-04-14 06:57:59
【问题描述】:

当我阅读 MDN(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Sub_classing_with_extends) 关于继承类中的属性时,他们说我需要使用 Object.setPrototypeOf()

class Book {
  constructor(title) {
    this.name = "Book";
    this.title = title;
  }
}

Object.setPrototypeOf(Book.prototype, {
  state: 'OH',
  country: 'US'
})

let newBook = new Book('Lolita')
console.log(newBook.state) //OH

但是当我查看 MDN 关于 Object.setPrototypeOf() 时,他们说它很慢,应该使用其他的,例如 Object.create()。但是当我尝试时它不起作用

class Book {
  constructor(title) {
    this.name = "Book";
    this.title = title;
  }
}

Book.prototype = Object.create({
  state: 'OH',
  country: 'US'
})

let newBook = new Book('Lolita')
console.log(newBook.state) //undefined

我认为这很奇怪,因为使用正常的原型语法 Object.create() 工作得很好。而且 Book.prototype 是对象,所以我看不出有什么理由不能添加这样的原型。

注意:在我阅读了@Felix 的第一个答案后,这似乎是合理的。但是当我尝试稍微调整代码时,我发现其他地方它不应该工作但结果它工作

class Book {
  constructor(title) {
    this.name = "Book";
    this.title = title;
  }
}

Object.setPrototypeOf(Book.prototype, {
  state: 'OH',
  country: 'US'
})

class LibraryBook extends Book{}
LibraryBook.prototype = Object.create(Book.prototype)
let firstBook = new LibraryBook('Lolita')
console.log(firstBook.state)

你能解释一下这个案例为什么有效吗?

【问题讨论】:

    标签: javascript inheritance ecmascript-6


    【解决方案1】:

    当您使用class 语法时,生成的构造函数的prototype 属性不可写且不可配置。这意味着您不能通过赋值表达式或Object.defineProperty 为其分配新值。

    class Book {}
    
    console.log(Object.getOwnPropertyDescriptor(Book, 'prototype'));

    你能解释一下这个案例为什么有效吗?

    LibraryBook.prototype = Object.create(Book.prototype) 无效。您可以删除它并获得相同的结果。 LibraryBook.prototype 已经是一个以Book.prototype 为原型的对象。这就是... extends Book 子句的作用。

    class Book {}
    class LibraryBook extends Book {}
    
    console.log(Object.getPrototypeOf(LibraryBook.prototype) === Book.prototype);

    【讨论】:

    • 所以Object.setPrototype() 工作是因为它重写了整个原型,而Object.create() 不能工作,因为它只为它分配新值,对吗?
    • 它之所以有效,是因为它(在内部)改变了Book.prototype 的值,它不会创建(和分配)新对象。 IE。 var obj = {}; var oldObj = obj; Object.setPrototypeOf(obj, {}); console.log(obj === oldObj);truevar obj = {}; var oldObj = obj; obj = Object.create({}); console.log(obj === oldObj);false
    • 我添加了一个子类,发现Object.create() 在这种情况下适用于子类。这是否与您在上面写的相反?
    • 没有。 LibraryBook.prototype = Object.create(Book.prototype) 无效。您可以删除它并获得相同的结果。 LibraryBook.prototype 已经是一个以Book.prototype 为原型的对象。这就是... extends Book 子句的作用。 class Book {}; class LibraryBook extends Book {}; console.log(Object.getPrototypeOf(LibraryBook.prototype) === Book.prototype);true
    • 我在 MDN 中读到使用 Object.setPrototypeOf() 会影响性能。有什么办法可以避免这个问题。在类中设置私有或公共变量尚未标准化
    猜你喜欢
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 2021-05-05
    • 2011-12-14
    • 2017-08-19
    相关资源
    最近更新 更多