我试图完全掌握关于Object.create的MDN文档,但我留下了一些我无法解决的问题。
以下是MDN提供的示例代码。
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info("Shape moved.");
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); // call super constructor.
}
// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
我不理解的一行是Shape.call(this)。我查了一下Object.call(这个),但我找不到任何关于它的文档。这行代码在做什么?
此外,这一行:Rectangle.prototype.constructor = Rectangle;将构造函数设置为Rectangle的好处是什么?
最后,为什么有人会使用Object.create()来执行这样的操作:
Rectangle.prototype = new Shape()
谢谢!
答案 0 :(得分:1)
.call()
是所有Function对象的方法。 Shape
是一个函数,因此它具有该方法。 .call()
here的文档。
代码Shape.call(this)
表示要调用Shape函数,当您调用它时,请将该函数的this
指针指向当前值this.
。
该行代码的目的是调用基础对象的构造函数。
设置:
Rectangle.prototype.constructor = Rectangle
是对象存储创建它的构造函数的位置。它可以被其他代码用来在尝试从它继承时调用该类的构造函数,当尝试创建这种类型的另一个对象时(不知道它究竟是什么类型 - 假设它需要任何参数) )和各种各样的功能。
Object.create()
有许多用途,但在您的特定代码示例中,它用于创建一个新对象,该对象具有对继承有用的特定对象的原型。您可以阅读更多相关信息here。
答案 1 :(得分:1)
当函数执行时,this
关键字指向上下文 - 调用该函数的对象。可以使用this
上可用的call()或apply()方法显式指定Function.prototype
的值。这些函数有两个参数;第一个是this
的值的对象。当使用call()或apply()时,使用参数对象作为其上下文调用该函数(该函数被称为对象的方法)。
您还需要了解,当函数用作构造函数时,将创建一个对象,并使用新创建的对象作为其this
值执行该函数。新创建的对象还继承了构造函数的prototype
属性的方法和属性。
在您的示例中,Rectangle
构造函数正在尝试继承Shape
构造函数的属性和方法。
function Rectangle() {
Shape.call(this);
}
当创建Rectangle
的实例时,将使用新创建的Shape
实例作为其Rectangle
来调用this value
函数。 Shape
函数中的所有初始化代码都在新创建的Rectangle
实例上运行。
Rectangle.prototype.constructor = Rectangle;
创建函数时,会自动创建其prototype
属性。 prototype
属性是一个具有constructor
对象的对象,该对象指向构造函数。
Object.create(proto)创建一个新对象,其原型是提供给它的参数的值。
Rectangle.prototype = Object.create(Shape.prototype)
实际创建了一个新对象,该对象继承了Shape.prototype
的方法,并将此对象分配给Rectangle.prototype
。这将覆盖自动创建的原始prototype
对象。因此,您需要使用constructor
在prototype
对象上明确定义Rectangle.prototype.constructor = Rectangle
属性。
答案 2 :(得分:0)
嗯,这是一个面向对象的结构,所以你应该在开始之前了解OOP。如果你已经这样做了,让我解释一下发生了什么:
你正在创建的Rectangle“class”继承了Shape“class”。
因此,函数Rectangle调用Shape构造函数,然后Rectangle类将属性x和y初始化为0,与Shape类完全相同。
“Rectangle.prototype.constructor = Rectangle”行仅声明Rectangle类构造函数是您刚刚在上面声明的函数。
因此,当您开发一个新的Rectangle实例时,您将编码:
var myRectangle = new Rectangle();
当你这样做时,它将调用Rectangle构造函数,它将自动调用Rectangle函数,这个将调用Shape构造函数,然后你的Rectangle对象将具有属性x和y。
尝试在某些浏览器中调试它,你会看到我在说什么。
在C#中,等效代码如下:
public class Shape
{
public int X { get; set; }
public int Y { get; set; }
public Shape()
{
this.X = 0;
this.Y = 0;
}
public void Move(int x, int y)
{
this.X = x;
this.Y = y;
}
}
public class Rectangle : Shape // inherits the class Shape
{
public Rectangle() : base() // inherits the Rectangles constructor from Shape's constructor
{
}
}
由于Javascript不是一种原生的面向对象编程语言,你需要做那些“黑客”来创建“类”(我一直在使用引用,因为它只是一个类的模拟),以及其他hacks继承那些类等。