Javascript - 理解Object.create和Object.call(this)

时间:2014-04-04 01:55:53

标签: javascript inheritance

我试图完全掌握关于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()

谢谢!

3 个答案:

答案 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对象。因此,您需要使用constructorprototype对象上明确定义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继承那些类等。