如何在JavaScript原型继承真的有效?

问题描述 投票:4回答:6

我还没有完全理解继承dychotomy(原型与古典)在JavaScript中。

如果class刚过原型一个语法糖,怎么我应该去糖呢?

愿你告诉我在创造与反应类和原型元素的不同方法(不classReact.createClass即)?

那么,有没有一种方法使用本地Object.create拿到状态组件?

像这样:

const Hello = Object.create(React.Component.prototype, {
  componentDidMount: {
    value: function() {
      alert('Mounted');
    }
  },
  render: {
    value: function() {
      return <div>I love StackOverflow community! It is so helpful and friendly</div>;
    }
  }
});

ReactDOM.render(<Hello />, document.getElementById('root'));

似乎这样的事情不会因为内部的lib的限制问题。但是,为什么我们不能在更自然的使用它为JavaScript的原型本质是什么?

有从官方文档的说明:https://facebook.github.io/react/docs/composition-vs-inheritance.html#so-what-about-inheritance

[...]我们还没有发现任何使用情况下,我们会建议创建组件继承层次

但是,是不是大多class关于继承?

我很迷茫,想听听你的我在做什么和想错了的意见?

我问这个问题在Reactiflux和布伦丹·赫尔利提出这样的:https://codepen.io/niechea/pen/xdVEvv?editors=0010

function MyComponent(props) {
  this.props = props;
  this.state = {
    clickCount: 0,
  };
}

MyComponent.prototype = Object.create(React.Component.prototype);

MyComponent.prototype.clickHandler = function() {
  this.setState({
    clickCount: this.state.clickCount + 1,
  });
}

MyComponent.prototype.render = function() {
  return (
    <div>
      <p>Hello, {this.props.name}.</p>
      <p>You have clicked {this.state.clickCount} time(s)!</p>
      <button onClick={this.clickHandler.bind(this)}>Click me</button>
    </div>
  );
}

ReactDOM.render(<MyComponent name="Bogdan" />, document.getElementById('app'));

是他的解决方案真正的原型?


下面是一些参考:


*现在的问题主要是关于继承,不是反应。反应在这里只是一个参考。

javascript reactjs inheritance
6个回答
2
投票

如果类是刚刚超过原型一个语法糖,怎么我应该去糖呢?

例如,这是对此事进行了good article。所以,如果你有使用Animal创建一个实体class

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

    doSomething() {
        console.log("I'm a " + this.name);
    }
}

var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();

原型版本将是这个样子:

var Animal = (function () {
    function Animal(name) {
        this.name = name;
    }
    // Methods
    Animal.prototype.doSomething = function () {
        console.log("I'm a " + this.name);
    };
    return Animal;
})();

var lion = new Animal("Lion");
lion.doSomething();

这是一个与extend功能(例如,打字稿继承模拟)更加复杂:

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

愿你告诉我在创造与反应类和原型元素的不同方法(无级及React.createClass即)?

另外还有SO已经回答了这个问题的问题,例如this one

但尽管如此,在我看来,真正的问题是:你想不想?

既然你挂埃里克·艾略特的文章,你可能会注意到,有一种围绕EC6的classes纠纷在javascript中的世界。除了您发布的例子,还有来自更多的开发者,例如意见一些聚集this github repohere多。也有文章卫冕class的目的...

无论如何,创作者的反应似乎已经接受了classes的“邪恶”,正如你指出要使用与之反应原型方法时,你会碰到的问题。所以,在我看来:为什么打扰它?我太喜欢的JavaScript更多的原型性质和我也很喜欢ReactJS框架,但在我看来,这将是更好地想出一些新的框架,它结合了两个最好的,像“Protypal响应”,而不是试图强制原型就当它不用于这种用途反应。

但是,是不是类主要是关于继承?

这可能是回答的意见,但没有。类都有其优点为拥有继承Composition的设计理念。它depends on the needs但许多框架/库建立在其上使用类怀抱组合物过度继承的面向对象的语言中,例如统一。

总之,非常好的问题,我想分享一下我对此事的看法了。希望它会帮助你形成意见。


1
投票

因此,像其他人所说,最好的办法去想类的Javascript是在原型继承语法糖。这是最好避免在其他语言的经典的继承和类之间的关联,特别是如果你一直在教导我的大学/学院。

原型继承可以被认为是比传统的继承more expressive

使用JS中的“类”的关键字是语法上更接近于传统的继承。

例如,你在你的UI具有以下组件:链接,的MediaLink,与ImageLink的录象。在经典的继承,你可能想有一个链接类,扩展链接一类的MediaLink,而扩展的MediaLink类录象及类ImageLink的地方的MediaLink是一个抽象类(不能被实例化)。如果要实现这个层次具有状态作出反应使用原型继承组件,状态理论上可以很容易地通过调用超(或调用React.Component.apply(this, props);如上答案),发生反应不过核心,即“渲染”会有点操纵抽象并难以扩展。链接可能会返回<a ...>link</a>,将一个返回的MediaLink什么?如何将一个视频链接与其父的复出之作?或者你开始否定父渲染功能,完全取代他们?它得到尴尬的在这一点上,它开始看起来有点像意大利面条。

相反,你可以撰写的组件。在经典的继承,你可以把你的组件类的作为已经从一个抽象类,继承React.Component final类。为了实现上述,您可以添加行为的类,它可能是共同的很多类。例如,组件文本链接,视频链接和所有ImageLink的有一个布尔状态“点击”。我认为this article总结了这些想法非常好。

构成部件的另一种方式是通过包装与其他部件的部件,并通过道具穿过状态到自己的孩子。一个非常粗的例子可能是:链接,SwitchedLink。 Link类具有道具“活跃”,其确定其是否处于活动状态。交换链接将根据自身状态呈现两种<Link /><Link active />作为一个孩子。孩子是无状态的。母公司拥有的状态。这些都是与之反应常见的模式,因此为什么没有必要古典多级继承结构。

我希望能够解决你的问题。


0
投票

在发生反应,有两种类型的组分;功能部件和基于类的组件。这里是一个link到方式的差分的反应文档。

需要注意的一个有趣的事情是,在反应的成分基本上是JSX返回一定量的函数。所以,你可以编写一个函数,使其返回JSX,这将是一个组成部分,但没有钥匙的内部细节,如lifecycle methodscomponentWillMountthis.propsthis.stateClass Component会提供给你开箱。

所以,你可以创建一个功能组件(即返回JSX功能),并有原型在它像这样

const Card = (props) => {
this.sayHello = function () {
  console.log('hello hello hello');
};

return (  
  <View style={styles.containerStyle}>
    {props.children}
    { this.sayHello() }
  </View>
 );
};

这将通过对创造了反应,而不必你来正常术语的组件。

希望这是有益


0
投票

对不起,我不能写任何评论。我想你一定低于初始化超类的构造函数。

function MyComponent(props) {
  React.Component.prototype.apply(this, props);
  this.props = props;
  this.state = {
    clickCount: 0,
  };
}

0
投票

我认为其重要,打破下来易于理解的方式。你问有关在JavaScript原型继承以及如何适用有关反应。首先,我不得不说,原型是不容易解释,也不是有据可查的,但在同一时间让专注于一件事情。所以,是的,JavaScript没有对象继承的概念,而是原型继承。让我们创建一个汽车功能:

function Car() {

}

然后,我们可以做一个丰田将从Car继承。所以,让我们看看一个构造函数的外观不使用类时等。

function Car(options) {
  this.title = options.title;
}

所以,每一个Car必须有options传递给它,这optionstitle

现在,我们可以创建一个新的汽车,并通过它像这样optionstitle对象:

const car = new Car({ title: 'Focus' });
car;

现在,让我们在这个Car类添加一个方法,所以我们将这个方法来像这样的构造函数的原型对象:

Car.prototype.drive = function() {
  return 'vroom!';
}

现在,当我们调用car.drive();我们得到vroom!的结果。

因此,这是基本的对象创建使用JavaScript。我们创建构造对象,然后使用就可以了new关键字,然后我们可以添加方法的对象,但我们增加它的构造函数的原型属性:

constructorFunction.prototype.methodWeAdd = function() {
  return something;
};

现在,我将添加一个对象将从Car继承来建立原型链接。

所以,我会做一个丰田汽车,我希望它像来自所以这Car对象继承:

function Toyota(options) {

}

所以,我通过它的options对象包含汽车的color参数。

function Toyota(options) {
  this.color = options.color;
}

const toyota = new Toyota({ color: 'grey', title: 'Prius' });
console.log(toyota);

所以,我想是因为Cartoyota丰田继承所有属性和Car的方法。那么,如何建立两者之间的联系?如何委派toyota能够调用所有Car所拥有的方法?

所以每当我打电话Toyota构造我要确保我运行发生在Car以及像这样的初始化:

function Toyota(options) {
  Car.call(this.options);
  this.color = options.color;
}

我也希望确保我可以从Car对象调用Toyota驱动方法如下所示:

Toyota.prototype = Object.create(Car.prototype);
Toyota.prototype.constructor = Toyota;

现在,我应该能够添加到Toyota原型,像这样的方法:

Toyota.prototype.honk = function() {
  return 'beep beep!';
};

现在,我应该能够调用以下:

const toyota = new Toyota({ color: 'grey', title: 'Prius' });
console.log(toyota);
console.log(toyota.drive());
console.log(toyota.honk());

所以toyota应该继承是从Car来设定的某一水平。所以上面痛苦的过程,我只是把我自己通过,是对你说,这是你将如何去糖它以纯香草的JavaScript。不知道为什么你会想,但在这里它是。

所以上面的是如何继承原型在JavaScript中完成。

类的想法不只是为它的缘故语法糖,这是从我们的工作量删除这样的艰苦的过程,所以我们可以专注于应用程序开发的其他挑战。

当你看到新的发展,如与ES6,是一些它陷入语法糖,但这个想法是从一个日常任务,删除或解决一个艰苦的过程,如创建类或对象访问属性/方法,如与解构。

在实践中,JavaScript社区已经接受了使用类,你会看到一吨利用类的库,而模板字符串和拆解是一个很好的补充,类别发生了巨大变化,我们编写JavaScript代码的方式。

很多的,这是由于它是多么的困难写原型继承而使用类的使用classextend关键字轻松了许多。

当反应过来先出来,使用原型继承所有的地方创建组件的想法被认为是可笑只是因为你必须做的(如你在上面看到的)这么多的设置,只要你创建,从另一个继承的子类宾语。取而代之的是,创造一个组成部分,我们将使用createClass帮手。这是阵营的一部分,但我要告诉你的,其中一些现有的库向迁移类的实例。

因此,它使用的是的情况下,与反应,我们有这个助手叫createClass像这样:

React.createClass({

});

你会通过在一个对象,它可能有像这样的方法:

React.createClass({
   doSomething() {

   },

   doSomethingElse() {

    }
});

这不是世界上最糟糕的事情,但它肯定使它真的很难,只要你想继承的组件或者创建拥有一些关于行为的一个组成部分,并重新使用它在其他地方。这几天的反应已经迁移对使用类,而不是语法,例如:

class MyComponent extends Component {
    doSomething() {

    }

    doSomethingElse() {

    }
}

这种方法的好处是,如果我要拍一些通用的,很可重用的组件到别的地方使用我的代码库,我可以用基于类的方法这样做更容易,而不是使用createClass()语法和肯定比更容易原型继承语法的方式。

您还会注意到继承链更加明显。所以这个组件关键字是由阵营库提供了一个通用组件。

任何人谁在这个类几眼可以看到,它的创建组件和Component借用功能。

这样做的好处是,如果你是面向对象编程,并与工作做出反应的粉丝,类语法通常更容易比老createClass()语法工作。


0
投票

原型继承是当你把一个方法对原始构造这里

function Cat(name,breed){
   this.name = name;
   this.breed = breed;
}

它会通过他们的休息继承

const susie = new Cat('Susie', 'Persian');

如果我创建一个新的数组,const names = ['Gilbert','Mia']我只是装箱,一个全新的阵列,但现在names.join()是一种方法names.pop)()是一种方法。

enter image description here

我们有名字的顶部所有这些方法。在哪里,他们从COM?那么,我们有母亲Array大写A

如果你看看它的内部,你就会知道,Array有很多的原型方法,

enter image description here

这意味着,当你创建Cat

const susie = new Cat('Susie', 'Persian');

从母阵列或从母亲Cat

function Cat(name,breed){
   this.name = name;
   this.breed = breed;
}

的,每一个实例继承这些方法。

function Cat(name,breed){
   this.name = name;
   this.breed = breed;
}
Cat.prototype.meow = function() {
   Console.log(`Meow meow! My name is ${this.name}`);
}

const susie = new Cat('Susie', 'Persian');
const mimi = new Cat('Mimi', 'Persian');

现在你可以看到Cat.prototype.meow现在由每个实例猫继承了原型。

const susie = new Cat('Susie', 'Persian');
const mimi = new Cat('Mimi', 'Persian');

susie.meow(); - >喵喵!我叫苏西mimi.meow(); - >喵喵!我的名字叫咪咪

© www.soinside.com 2019 - 2024. All rights reserved.