了解JS中的原型继承方法 [英] Understanding Prototypal Inheritance methodologies in JS

查看:89
本文介绍了了解JS中的原型继承方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了Google第一页上的所有文章和示例,但仍然很难完全理解如何在JavaScript中正确实现原型继承.我面临的最大挑战是,我看到了实现继承的许多不同方法.

I have read every article and example on the first page of Google and I still am having a hard to completely understanding how to properly implement Prototypal Inheritance in JavaScript. The biggest challenge I'm facing is I am seeing many different ways to implement the inheritance.

首先,如果要使用C#,我将从我要实现的目标开始:

First I will start with what I want to achieve if this was C#:

C#

class Base {
    public string UI { get; set; } // Using a string just for simplicity
}

class Book : Base {

    public Book(string title) {
        this.title = title;
    }
    private string title { get; set; } // Title of book
}

然后,我可以实例化一本书,并能够在每个实例上访问UI:

Then I can instantiate a Book and be able to access UI on each instance:

var myBook = new Book("East of Eden");
myBook.UI = "some string"; // This work.. all Book instances have THEIR OWN UI string

JavaScript

现在可以说我在JS中有一个基础对象,我希望所有其他对象都可以从中继承:

Now lets say I have a base object in JS that I want all other objects to inherit from:

function Base() {
    this.UI = {}
}

然后我想要另一个对象类型像这样继承该模型:

I then want another object type to inherit this model like this:

function Book(title){
    this.title = title;
}

Book.prototype = new Base();
// Sometimes I have seen this line instead... nothing seems to work at all when I use this though, so I don't understand whats happening here
//Book.prototype = Object.create(Base.prototype);
Book.prototype.constructor = Book;

Book.prototype.getTitle = function(){
    return this.title;
}

var myBook = new Book("East of Eden");
var anotherBook = new Book("Grapes of Wrath");

console.log(myBook.getTitle()); // East of Eden
myBook.UI.isRead = true;
console.log(myBook.UI);

console.log(anotherBook.getTitle()); // Grapes of Wrath
anotherBook.UI.isHardcopy = true;
myBook.UI.isRead = false;
console.log(anotherBook.UI); // This UI object has isRead on it as well!!! NOOOO

所以这实际上不起作用,因为两个实例都共享同一个UI对象,但是我要的是让他们拥有UI对象的OWN实例.

So this doesn't really work because both instances are sharing the same UI object, but what I want is for them to have their OWN instance of the UI object.

我看到的另一种方法是根本不使用'new'关键字,而仅使用Object.create()来获取新对象.但是,我不确定如何用Book之类的子类实现Base类,然后创建Book的多个实例,每个实例都有自己的UI属性.

Another method I have seen is to not use the 'new' keyword at all and only use Object.create() to get new objects. However, I am not sure how I would implement my Base class with some subclass like Book and then create multiple instances of Book, each with their own UI properties.

有人可以给我一个例子,说明如何继承基类并使用自己的UI对象创建该子类的实例吗?谢谢

Could someone please give me an example of how to inherit a base class and create instances of that subclass with their own UI objects? Thanks

编辑

实现我想要的目标的简单"方法也将是做类似的事情:

So would the "simple" way of achieve what I want just be to do something like:

var Base = {
    UI: {}
}

function Book(title){
  _.extend(this, Base);
  this.title = title;
}

var myBook = new Book("East of Eden");
myBook.UI.prop = 5; // This works now but doesn't utilize true inheritance at all!

推荐答案

原型已链接且未复制.这意味着当您这样做时:

Prototypes are linked and not copied. This means that when you did:

function Base(){
    this.UI = {}
}

Book.prototype = new Base();
Book.prototype.constructor = Book;

Book构造函数的原型将是Base的新实例.您所有的Book实例都将具有相同的原型,相同的Base实例.由于拥有UI属性的是该对象,因此所有Book实例都将回退到相同的对象属性.

The prototype of your Book constructor will be a new instance of Base. All your instances of Book will have the same prototype, the same instance of Base. Since it's this object which holds the UI property, all Book instances will fallback to the same object property.

认为您的原型应为:

var proto = {
   UI : { }
}

您的所有Book实例都可以访问该对象:

All your Book instances will have access to this object:

var a = new Book('East of Eden');
var b = new Book('Grapes of Wrath');

a.UI.prop = 'prop'; //proto.UI.prop === 'prop'
b.UI.prop === 'prop'; //because it's also proto.UI.prop

如果您实际上在Book实例上定义了属性,请说说其构造函数:

If you actually define a property on Book instances, say on its constructor:

function Book(title){
    this.title = title;
    this.UI = { };
}

您将看到它们是不同的对象:

You'll see that they are different objects:

a.UI !== b.UI //true
a.UI.prop = 'prop';
b.UI.prop !== b.UI; //true

调用构造函数是最明显的方式,也可以初始化其子级的属性:

Calling the constructor is the most obvious way to also initialize the properties on their children:

function Book(title){
     Base.call(this);
     this.title = title;
 }

关于new Base()Object.create(Base.prototype)之间的区别.

new Base()将初始化对象并调用构造函数,而Object.create(Base.prototype)会执行相同的操作,只是不会调用构造函数.这意味着原型将没有在构造函数(UI)上设置的属性.

new Base() will initialize the object and call the constructor, while Object.create(Base.prototype) will do basically the same, except it won't call the constructor. This means, that the prototype won't have the properties set on the constructor (UI).

这篇关于了解JS中的原型继承方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆