javascript 如何正确使用Object.setPrototypeOf()

dfty9e19  于 2023-01-24  发布在  Java
关注(0)|答案(3)|浏览(144)

所以我一直在快速学习JavaScript的一些新特性,并且一直在阅读关于Object.setPrototypeOf()的内容。我偶然发现了MDN中的这段代码,它处理从常规对象继承的问题。但是我对他们在这里如何使用Object.setPrototypeOf()感到困惑。我希望他们写

Object.setPrototypeOf(Dog, Animal)

而不是下面他们做的。他们为什么这样写?

var Animal = {
   speak() {
     console.log(this.name + ' makes a noise.');
   }
};

class Dog {
   constructor(name) {
   this.name = name;
  }
}

Object.setPrototypeOf(Dog.prototype, Animal);// If you do not do this you will get a TypeError when you invoke speak

var d = new Dog('Mitzie');
d.speak(); // Mitzie makes a noise.
niknxzdl

niknxzdl1#

调用Object.setPrototypeOf的原因是为了确保任何由Dog构造函数创建的对象都能在其原型链中获得Animal对象。设置构造函数本身的原型是错误的(不要与构造函数的prototype属性混淆,后者实际上是一个用词不当),因为构造函数在d的原型链中没有位置。
创建的Dog对象在其原型链中不获得Dog,但是Dog.prototype . Dog * 只是 * 创建对象的载体,它本身不应该成为原型链的一部分。
您 * 可以 * 在Dog构造函数中执行此操作:

Object.setPrototypeOf(this, Animal)

这使得原型链的长度缩短了一步,但缺点是现在d instanceof Dog将不再是真的,它将只是一个Animal,这是一个遗憾,这也解释了为什么保留原来的Dog.prototype对象是好的,而将 * 其 * 原型设置为Animal,因此现在d既是Dog又是Animal
阅读关于这个主题here的文章。我会把my own answer推广到那个问答中。

vwkv1x7d

vwkv1x7d2#

1)Animal是Object文字
2)对象文本没有prototype属性
3)语法为

Object.setPrototypeOf(targetObj, sourceObj);
Object.setPrototypeOf(Dog.prototype,Animal);

4)通过这样做,我们继承了的属性
对象文本(Animal)到另一个文本或构造函数(Dog
5)在这里,狗的原型是从动物设定的。
此方法(Object.setPrototypOf())将对Animal的方法的引用设置为对Dogprototype的引用

yduiuuwa

yduiuuwa3#

我们可以使用{__proto__:...}来做同样的事情:

var Animal = {
   speak() {
     console.log(this.name + ' makes a noise.');
   }
};

var Dog={
  __proto__: Animal
}

Dog.name='Mitzie'
Dog.speak(); // Mitzie makes a noise.

{__proto__: Animal}是定义prototype chain的一种方式,这里是动物中定义的{__proto__: {speak:function(){...}}
为了理解这一点,我们来看看这个链的步骤。当我们这样做Dog.speak() js不能找到函数speak内的狗。所以它向上链一次,并找到speak内的动物。正如预期的输出“Mitzie制造噪音。"
从概念上讲,Object.setPrototypeOf(Dog.prototype, Animal)Dog.prototype.__proto__=Animal相同,我们将此设置Dog.prototype.[[Prototype]]称为Animal,[[Prototype]]是指向链上一级对象的链接。

var Animal=function() {}
Animal.prototype.speak=function() {
    console.log(this.name + ' makes a noise.');
}

var Dog=function(name) {
    this.name=name
}

// set up prototype chain
Dog.prototype.__proto__=Animal.prototype

var d = new Dog('Mitzie');
d.speak(); // Mitzie makes a noise.

下面的示例替换为使用__proto__定义原型链。

var Animal = {
   speak() {
     console.log(this.name + ' makes a noise.');
   }
};

class Dog {
   constructor(name) {
   this.name = name;
  }
}

//Object.setPrototypeOf(Dog.prototype, Animal);// If you do not do this you will get a TypeError when you invoke speak
Dog.prototype.__proto__=Animal

var d = new Dog('Mitzie');
d.speak(); // Mitzie makes a noise.

最后,您可以只使用class extends..

var Animal = class {
    constructor(name) {
    this.name=name
  }
   speak() {
     console.log(this.name + ' makes a noise.');
   }
};

class Dog extends Animal {
   constructor(name) {
     super(name)
  }
}

var d = new Dog('Mitzie');
d.speak(); // Mitzie makes a noise.

正如您所看到的,这种方法是推荐的最简单的方法;)

相关问题