1

由于对原型继承的了解较少,我陷入困境。我想知道原型继承到底是什么以及它是如何实现的。

你能举一个简单的例子吗?
任何帮助表示赞赏。

4

3 回答 3

1

在其核心

想象一下,您有一个对象,并且想要查找一个属性。现在想象该属性不存在。如果您可以让它自动继续在不同对象上搜索该属性怎么办?这基本上就是原型继承。


我们该怎么做呢?

那么唯一的问题是如何在对象之间建立这种关系。嗯,这就是奇怪的部分。

我将从主要的历史方式开始。那就是使用函数。

首先要注意的是,JavaScript 中的函数本身就是一个对象。它可以有自己的属性,并且它使用原型继承来访问其他属性。

所以让我们从创建一个函数开始。

function Foo() {
    // our function
}

所以现在我们有一个名为Foo. 我们的新函数在创建时会自动获取一个命名的属性prototype。该属性引用了一个(几乎)空对象。

console.log(typeof Foo.prototype); // object

为什么该属性和对象存在?嗯,它们的存在是为了支持 JavaScript 在我上面描述的对象之间形成这种关系的奇怪方式。

基本上,该Foo.prototype对象是我们在寻找对象的新属性时将用作“备份”对象的对象。但是我们还没有在我们想要使用的对象和Foo.prototype对象之间形成任何特殊的关系。


让它发挥作用

为此,我们实际上使用new运算符调用函数。

var my_object = new Foo();

我们开始了。所以现在my_object是一个新的空对象。但它在它的“原型链”中有一个对象,它从我们的Foo函数中悬挂下来,脱离了它的.prototype属性。换句话说,当我们在 上查找属性时my_object,如果该属性不存在,它将继续在该Foo.prototype对象上进行搜索。


看到它在行动

问题是我们没有添加任何我们可能会觉得有用的东西Foo.prototype。但实际上该对象有一个属性。该属性也是在我们创建Foo函数时自动创建的,它就是.constructor属性。

该属性参考什么?它有一个对Foo函数的引用。换句话说:

Foo.prototype.constructor === Foo; // true

好吧,所以如果我们my_object是空的,并且如果在寻找my_object不存在的属性时,它会继续在Foo.prototype对象上搜索,那么这应该意味着我们应该能够自动Foo.prototype.constructormy_object.

my_object.constructor === Foo; // true

它有效。由于my_object没有名为 的属性constructor,它继续搜索它所继承的对象,即Foo.prototype,正如我们所知,它具有.constructor引用该Foo函数的属性。


为我们的代码定制

极好的。但是我们如何在代码中设置对我们更有用的其他属性呢?我们只是将它们添加到Foo.prototype. my_object如果对象不直接拥有它们,这将让我们找到这些属性。

// give a custom property to `Foo.prototype`
Foo.prototype.bar = "foobar";

// see if we can access that property on your object
my_object.bar === "foobar"; // true

果然,它奏效了。因此,让我们看看我们是否可以从中创建一个新对象,Foo该对象也可以访问该.bar属性。

var another_object = new Foo();

another_object.bar === "foobar"; // true

再次,它有效。这是因为通过Foo使用new关键字调用创建的所有对象都将在其原型链中包含该Foo.prototype对象。换句话说,在从创建的所有实例Foo.prototype之间共享Foo

因此,如果我们现在修改Foo.prototype.bar属性,它将反映在我们创建的两个对象中。

Foo.prototype.bar = "raboof";

my_object.bar === "raboof";      // true
another_object.bar === "raboof"; // true

所以我们可以看到,我们的两个对象都只是在寻找它们没有的属性,方法是将搜索传递给它们“原型链”中的下一个对象,也就是悬挂在Foo函数之外的那个奇怪的对象…… Foo.prototype


还有更多要学习

建立这种对象关系有更新的方法,但这是原始方法,尽管它很奇怪,但可能应该首先理解。

于 2013-06-27T14:11:53.063 回答
0

我是这样理解的:

这可以被认为是一个构造函数

var Thing = function(){
    this.method1 = function(){
        alert( "method 1" );
    }
}

这是它的一个实例

var a_thing = new Thing();

a_thing.method1();

现在,如果你在构造函数的原型中添加一些东西,它就会自动提供给已经实例化的对象。

Thing.prototype.method2 = function(){
    alert( "method2" );
}

a_thing.method2();

希望这可以帮助。

于 2013-06-27T13:40:30.030 回答
-1

这是我能想到的最简单的例子,
pizza 类通过使用这一行从 circle 继承:

pizza.prototype = new circle();

完整示例:

<html>
<head>
    <script>
        // base class
        function circle(radius){
            this.radius = radius;

            this.getArea = function ()
            {
                return (this.radius * this.radius) * Math.PI;
            };

            this.foo = function ()
            {
                return "circle foo";
            };

            return true;
        }

        // child class
        function pizza(flavour, radius){
            circle.call(this, radius);
            this.flavour = flavour;

            this.foo = function ()
            {
                return "pizza foo";
            };
            return true;
        }

        // Inheritance
        pizza.prototype = new circle();

        function Go(){
            // Instancing new object
            var myCircle = new circle(8);
            var myPizza = new pizza("Onion", 5);

            // Calling property
            var pizza_area = myPizza.getArea();

            // Calling override foo function
            var foo = myPizza.foo();

            // Calling foo base class
            var base = pizza.prototype.foo.call(myPizza);
            //Line.prototype.someFunction.call(myLine);

            var isBase = myCircle instanceof pizza;
            isBase = myPizza instanceof pizza;
        }

    </script>    
</head>
<body onload="Go();">

</body>
</html>
于 2013-06-27T13:38:16.327 回答