【问题标题】:javascript pseudo classical inheritance and prototypal inheritance example confusionjavascript伪经典继承与原型继承示例混淆
【发布时间】:2015-10-12 04:39:08
【问题描述】:

我真的不明白伪经典和原型继承之间的区别。看看下面的代码 sn-p。

原型:我能够理解这段代码(Douglas Crockford)。我有 更改了类名并添加了实现以便更好地理解,因为他的代码块在presentaiton中不完整。

var baseObject = {
    a : "old",
    firstMethod: function () {alert("First method");},
    secondMethod: function () {alert("Second method");}
};
var derivedObject = Object(baseObject);
alert(derivedObject.a);

derivedObject.thirdMethod = function () {alert("Third method");};
var derivedChildObject = Object(derivedObject);

derivedChildObject.firstMethod();
derivedChildObject.secondMethod();
derivedChildObject.thirdMethod();

伪经典:

由于方法不完整,我在他的演示文稿中没有从相同的代码 sn-p 中获得清晰,我去了互联网上的其他链接

http://javascript.info/tutorial/pseudo-classical-pattern

function Animal(name) {
  this.name = name
}

Animal.prototype = {
  canWalk: true,
  sit: function() {
    this.canWalk = false
    alert(this.name + ' sits down.')
  }
}

var animal = new Animal('Pet') // (1)

alert(animal.canWalk) // true

animal.sit()             // (2)

alert(animal.canWalk) // false

伪类的方案:

方法和默认属性在原型中。 原型中的方法使用 this ,它是当前对象,因为 this 的值只取决于调用上下文,所以 animal.sit() 会将 this 设置为 animal。

你能帮我提供正确的例子吗?您可以将 - Animal 用例或 baseObject 用例作为参考或提出您自己的示例

【问题讨论】:

  • 第二个例子“伪经典”不包括继承。继承仍然是原型......
  • 如果你提供伪经典的例子和简单的例子会很棒
  • @devnull69 澄清一下:你的意思是在 javascript 中,所有继承都是原型的吗?
  • @user2808054 正确

标签: javascript inheritance


【解决方案1】:

这是一个原型继承的例子

var Mammal = function() {
   this.isMammal = true;
};

var Cat = function() {
   this.meow = function() {
      alert('Cat says: MEOW!');
   };
};

Cat.prototype = new Mammal();
Cat.prototype.constructor = Cat;

var kitty = new Cat();
if(kitty.isMammal) {...}       // evaluates to true
kitty.meow();

原型继承是通过将原型重新分配给基类的实例来实现的。这将导致原型链总是以 Object.prototype 结尾

如果您正在寻找方法或成员,则从实例开始,然后沿着原型链向下走,直到找到方法/成员(或者您没有找到)。

我们示例中的 toString() 和 kitty 示例:

kitty.toString();

1. kitty instance doesn't have toString() method
2. Cat.prototype doesn't have toString() method
3. Mammal.prototype doesn't have toString() method
4. Object.prototype has toString() method, which will be called in the context of kitty

【讨论】:

  • 你的例子中下一行的意义是什么? Cat.prototype.constructor = 猫;
  • 因为通过重新分配原型,您也将构造函数重新分配给Mammal。所以如果你还想让Cat()成为猫的构造函数,你需要重新赋值
  • 非常感谢。我很清楚原型继承。能否请您也提供伪古典的例子?
  • 即使你称它为“伪经典”......它仍然是原型,即使你试图通过使用不同的方法调用来隐藏它。 Javascript中只有一种继承类型,它是原型的
  • @sunrise76 是的。您可以在没有 new 甚至没有构造函数的情况下使用原型继承,但即使您使用这些功能,结果仍然是原型
【解决方案2】:

您在对象原型级别定义canwalk 属性,这就是为什么在您实例化对象时您会在警报(animal.canWalk) 上得到true。在第二个警报中您收到false 的原因是同时您调用了将canWalk 设置为false 的sit 函数。

这就是为什么严格遵循原型继承模式并不是很好的做法:通常,实例希望拥有自己的所有属性副本。这就是为什么原型模式很少单独使用的原因。

最推荐的是使用寄生组合继承

组合继承是 JavaScript 中最常用的继承模式,尽管它并非没有效率低下。该模式最低效的部分是超类型构造函数总是被调用两次:一次是创建子类型的原型,一次是在子类型构造函数内部。

本质上,子类型原型以超类型对象的所有实例属性结束,只是在子类型构造函数执行时被覆盖。

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    SuperType.call(this, name); //second call to SuperType()

    this.age = age;
}

SubType.prototype = new SuperType(); //first call to SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};

为了克服超类型构造函数总是被调用两次的问题,我们可以使用以下技巧进行调整:我们不需要调用超类型构造函数来分配子类型的原型,而只需要一个超类型原型的副本:

function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); //create object
    prototype.constructor = subType; //augment object
    subType.prototype = prototype; //assign object
}

那么我们可以替换:

SubType.prototype = new SuperType(); //first call to SuperType()
SubType.prototype.constructor = SubType;

inheritPrototype(SubType, SuperType);

伪经典继承:

使用此模式,您可以定义对象级别的属性和对象原型级别的方法:

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype = {
    constructor: SuperType,
    sayName : function() {
        alert(this.name);
    }
}

如果在实例化调用instanceof 的对象时没有将构造函数指向SuperTypeObjectSuperType 仍然返回true,但构造函数属性现在等于ObjectSuperType

var superType = new SuperType();
alert(superType instanceof Object); //true
alert(superType instanceof SuperType); //true
alert(superType.constructor == Person); //false
alert(superType.constructor == SuperType); //true

继承示例:

function SuperType() {
    this.property = true;
}

SuperType.prototype.getSuperValue = function() {
    return this.property;
};

function SubType() {
    this.subproperty = false;
}

//inherit from SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function () {
    return this.subproperty;
};

//override existing method
SubType.prototype.getSuperValue = function () {
    return false;
};

这里有两个关于 Javascript 继承的非常有力的参考:

http://addyosmani.com/resources/essentialjsdesignpatterns/book/ http://www.allitebooks.com/professional-javascript-for-web-developers-3rd-edition/

【讨论】:

  • 非常感谢。我对原型继承很清楚,尤其是在构造函数部分。能否请您也提供伪古典的例子?
猜你喜欢
  • 2013-11-07
  • 2016-05-13
  • 2016-11-19
  • 1970-01-01
  • 2016-04-10
  • 1970-01-01
相关资源
最近更新 更多