简体   繁体   English

为什么Javascript默认不支持继承?

[英]Why Javascript does not support inheritance by default?

As from OOPS base , I always use inheritance as a powerful tool for code reuse, 从OOPS基础开始,我总是使用继承作为代码重用的强大工具,

Example, if I write a chess program in OOPS and when I implement a is-a relationship as, 例如,如果我在OOPS中写一个国际象棋程序,当我实现一个is-a关系时,

Class Piece{
  int teamColor;
  bool isLive;
  Positon pos;
  int Points; 
  .......
  int getTeamColor(){....}
  .......
};

Class Rook extend Piece{  //`is-a`
...... // No getTeamColor() definition here.. because the parent has the definition.
};

Class Pawn extend Piece{  //`is-a`
......// No getTeamColor() definition here.. because the parent has the definition.
};

I could do this with has-a relationship in javascript, but the drawback I am seeing is, I have to redefine every function in the derived class too. 我可以用javascript中的has-a关系来做到这一点,但我看到的缺点是,我必须重新定义派生类中的每个函数。

Example : redefinition of getTeamColor() again in every rook,knight,pawn,king.... etc.. 示例:在每个车,骑士,典当,国王......等中再次重新定义getTeamColor()。

     var Pawn = function(teamColor,pos){
     var piece = new Piece(teamColor,pos);
     .......

     this.getTeamColor = function(){        
          return piece.getTeamColor();
    };
    }

My question is, Why javascript doesnot support classical inheritance as a default option? 我的问题是,为什么javascript不支持经典继承作为默认选项?

[Update in 2018] JavaScript now obviously supports inheritance with native language features. [2018年更新]现在,JavaScript显然支持使用本机语言功能进行继承。

class A { }
class B extends A { }

[/Update] [/更新]

JavaScript does support inheritance on a prototypal way. JavaScript确实支持原型方式的继承。 What you need here is not classes but the encapsulation of behavior and the ability to override. 你需要的不是类,而是行为的封装和覆盖的能力。

function Piece() { }

Piece.prototype.color = "white";
Piece.prototype.getColor = function() { return this.color }
Piece.prototype.move = function() { throw "pure function" };

function Pawn() { }
Pawn.prototype = new Piece();    
Pawn.prototype.move = function() { alert("moved"); }

and now: 现在:

var p = new Pawn(); p.color = "black";

> p instanceof Piece

true 真正

 p instanceof Pawn

true 真正

p.getColor()

"black" “黑色”

p.move()

alert... 警报...

This is the basic approach and there are many libraries out there that turn this into something that is familiar for the guys wanting classes - so to say. 这是基本的方法,并且有许多库将这变成了对于想要课程的人来说熟悉的东西 - 所以说。

For example with JayData you can write the previous in a more encapsulated way (with the bonus of automatic constructor invocation up the chain: 例如,使用JayData,您可以以更加封装的方式编写前一个(在链上自动构造函数调用的奖励:

var Piece = $data.Base.extend("Piece", {
  move: function()  {  throw "pure class" } 
});

var Pawn =  Piece.extend("Pawn", {
  move: function() { ... }
});

var p = new Pawn();

Because Javascript is not a class-based object-oriented language , but rather a prototypal one. 因为Javascript不是基于类的面向对象语言 ,而是原型 语言 It's simply a design decision. 这只是一个设计决定。

Also, Javascript was never really "meant" for all the things we do with it today (from Node.js to ASM.js). 此外,Javascript从来没有真正“意味着”我们今天用它做的所有事情(从Node.js到ASM.js)。 The fact that it's still relevant is a testament Brendan Eich and Co. So you may wonder why X or Y was never implemented in JS, but the fact of the matter is that we use JS for things that 20 years ago would have been unforeseeable. 它仍然相关的事实是Brendan Eich和Co.的遗嘱。所以你可能想知道为什么X或Y从未在JS中实现,但事实是我们使用JS来解决20年前无法预见的问题。

Many good books on various traditional OO languages (including Java, C# and C++) specifically advise against using "implementation inheritance" where possible. 许多关于各种传统OO语言(包括Java,C#和C ++)的好书都特别建议不要在可能的情况下使用“实现继承”。 Example: Effective Java by Joshua Bloch. 示例:Joshua Bloch的有效Java。

The strange fact is that although implementation inheritance seems to give a regular "shape" to your code, it isn't really helping you solve a problem; 奇怪的事实是,虽然实现继承似乎给你的代码定期“形状”,但它并没有真正帮助你解决问题; more often, it causes problems in the long run. 更常见的是,从长远来看,它会导致问题。

Those authors tend to give their blessing instead to "interface inheritance" - but in a duck-typed language such as JavaScript there is no need to explicitly declare such inheritance. 那些作者倾向于给予他们的祝福而不是“接口继承” - 但是在诸如JavaScript之类的鸭子类型语言中,没有必要明确地声明这样的继承。

And in JS you can "reuse" the same function by simply assigning it as a property on multiple objects. 在JS中,您可以通过简单地将其作为多个对象的属性来“重用”相同的函数。 Whatever flavour of inheritance you need, you can conjure it up out of nothing. 无论你需要什么样的遗产,你都可以从无到有。

JavaScript does not even have real OOP-style classes, you're just able to simulate something similar. JavaScript甚至没有真正的OOP风格的类,你只能模拟类似的东西。

In your example, you can achieve inheritance by doing 在您的示例中,您可以通过执行继承

var Pawn = function(teamColor, pos) {
    Piece.call(this, teamColor, pos);
}

However, you should typically attach methods to the functions prototype rather than to any new created object. 但是,您通常应该将方法附加到函数原型而不是任何新创建的对象。 In that case, you can simulate inheritance by setting up a prototype chain, eg, like CoffeeScript does it: 在这种情况下,您可以通过设置原型链来模拟继承,例如,像CoffeeScript那样:

var a, b, _ref,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

a = (function() {
  function a() {}

  return a;

})();

b = (function(_super) {
  __extends(b, _super);

  function b() {
    _ref = b.__super__.constructor.apply(this, arguments);
    return _ref;
  }

  return b;

})(a);

The following code block will "extend" one JavaScript prototype from the other, and ensure that the "instanceof" operator works correctly for the base and derived classes. 以下代码块将“扩展”另一个JavaScript原型,并确保“instanceof”运算符对基类和派生类正常工作。

From what I can tell, setting TestB's prototype to a new TestA allows for the logical consistancy of the "instanceof" operator. 据我所知,将TestB的原型设置为新的TestA允许“instanceof”运算符的逻辑包含。

Passing this to TestA gives the new instance all the desired properties and methods. 将此传递给TestA会为新实例提供所有需要的属性和方法。

Doing it this way is a sort of balance between stylistic desires and pragmatic ones. 这样做是风格欲望和实用欲望之间的平衡。 This will work in most any browser, even Internet Explorer if you're forced to support it. 这将适用于大多数浏览器,甚至Internet Explorer,如果你被迫支持它。 It also helps because having the methods contained in the same block "feels" a lot like your traditional OO syntax. 它也有帮助,因为同一块中包含的方法“感觉”很像传统的OO语法。

Also, the main reason JavaScript doesn't support the traditional style of OO is because of its founding philosophy. 此外,JavaScript不支持传统的面向对象风格的主要原因是它的创始理念。 The founding philosophy is freedom. 创始哲学是自由。 This freedom is intended to allow developers to engineer their own styles to fit the project's needs. 这种自由旨在允许开发人员设计自己的样式以满足项目的需求。

function TestA(){
  var me = this;

  me.method = function(){
  }
}

function TestB(){
  TestA.call(this);
  var me = this;

  me.otherMethod = function(){
  }
}
TestB.prototype = new TestA();

var test = new TestB();

console.log(test);

console.log(test instanceof TestB);
console.log(test instanceof TestA);

//TestA { method: [Function], otherMethod: [Function] }
//true
//true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM