JavaScript语言对继承的使用

Posted 给自己一点正能量!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript语言对继承的使用相关的知识,希望对你有一定的参考价值。

  OOP语言都支持两个继承方式:接口继承和实现继承。在ECMAScript中支持实现继承,而且其实现继承主要是依靠原型链来实现的。

 

  

 

  每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。当我们让原型对象等于另一个类型的实例,那么就实现了继承。

  

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

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

//继承了SuperType
SubType.prototype = new SuperType();

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

var instance = new SubType();
alert(instance.getSuperValue());    //true
View Code

  在这里我们要注意继承时只继承父类的原型对象,如果是类的属性时,则会输出undefined;

function SuperType()
{
    this.property = true;
    this.sayName = function() {
        alert(this.name);
    }
}
SuperType.prototype.getSuperValue = function () {
    return this.property;
}

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

//继承了SuperType
SubType.prototype = new SuperType();

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

var instance = new SubType();
alert(instance.sayName());  //undefined
View Code

1.不要忘记默认的原型

  所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。

  

2.确定原型和实例的关系

  第一种方式是使用instanceof操作符

  

function SuperType()
{
    this.property = true;
    this.sayName = function() {
        alert(this.name);
    }
}
SuperType.prototype.getSuperValue = function () {
    return this.property;
}

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

//继承了SuperType
SubType.prototype = new SuperType();

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

var instance = new SubType();
alert(instance instanceof Object);  //true
alert(instance instanceof SuperType);  //true
alert(instance instanceof SubType);  //true
View Code

  第二种方式是使用isPrototypeOf()方法

alert(Object.prototype.isPrototypeOf(instance));  //true
alert(SuperType.prototype.isPrototypeOf(instance));  //true
View Code

3.谨慎地定义方法

  子类型在重写基类中的某个方法或者添加基类中不存在的某个方法时。一定要放在替换原型的语句之后。

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

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

//继承了SuperType
SubType.prototype = new SuperType();
//添加新方法
SubType.prototype.getSubValue =  function () {
    return this.subproperty;
}
//重写超类型中的方法
SubType.prototype.getSuperValue = function () {
    return false;
}

var instance = new SubType();
alert(instance.getSuperValue());
View Code

 4. 原型链的问题

  其中,最主要的问题来自包含引用类型值的原型。当使用原型对象时,所有包含引用类型值的原型属性与类的属性被所有实例共享。

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

function SubType()
{
}

//继承了SuperType
SubType.prototype = new SuperType();

var instance = new SubType();
alert(instance.colors);  //"red,blue,green"
instance.colors.push("black");
alert(instance.colors);  //"red,blue,green,black"

var instance2 = new SubType();
alert(instance2.colors);    //"red,blue,green,black"
View Code

  如果将SubType.prototype = new SuperType();去掉之后会变成

 

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

function SubType()
{
}

//继承了SuperType
// SubType.prototype = new SuperType();

var instance = new SuperType();
console.log(instance.colors);  //"red,blue,green"
instance.colors.push("black");
console.log(instance.colors);  //"red,blue,green,black"

var instance2 = new SuperType();
console.log(instance2.colors);    //"red,blue,green"
View Code

 

二:借用构造函数

  即在子类型构造函数的内部调用超类型构造函数。函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法也可以在新创建的对象上执行构造函数。

function SuperType()
{
    this.colors = ["red","blue","green"];
}
function SubType()
{
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors);   //"red,blue,green,black"

var instance2 = new SubType();
console.log(instance2.colors); //\'red\', \'blue\', \'green\'
View Code

三:组合继承

  组合继承,有时候也叫做伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承方式。其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上的定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

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

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

function SubType(name,age)
{
    //继承属性
    SuperType.call(this,name);
    this.age =age;
}

//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function()
{
    console.log(this.age);
}

var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
console.log(instance1.colors);  //"red,blue,green,black"
instance1.sayName();    //"Nicholas"
instance1.sayAge();     //29

var instance2 = new SubType("Greg",27);
console.log(instance2.colors);  //"red,blue,green"
instance2.sayName();    //"Greg"
instance2.sayAge();     //27
View Code

四:原型式继承

  这种方法并没有使用严格意义上的构造函数。它的思想是借助原型可以基于已有的对象创建新对象,同时还不比因此创建自定义类型。

function object(o)
{
    function F(){}
    F.prototype = o;
    return new F();
}
//从本质上讲,object()对传入其中的对象执行了一次浅复制
var person ={
    name:"Nicholas",
    friends:["Shelby","Court","Van"]
}

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
anotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.name);
console.log(person.friends);
View Code

  ECMAScripts5通过新增Object.create()方法规范化了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选)一个为新对象定义额外属性的对象。在传入一个参数的情况下,Object()与object()方法的行为相同。

var person ={
    name:"Nicholas",
    friends:["Shelby","Court","Van"]
}

var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = Object.create(person);
anotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.name);           //"Nicholas"
console.log(person.friends);        //[ \'Shelby\', \'Court\', \'Van\', \'Rob\', \'Barbie\' ]
View Code

  Object.create()方法的第二个参数鱼Object.defineProperties()方法的第二个参数格式相同:每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属性。

var person ={
    name:"Nicholas",
    friends:["Shelby","Court","Van"]
}

var anotherPerson = Object.create(person,{
    name:{
        value:"Greg"
    }
}
);
console.log(anotherPerson.name);
View Code

五:寄生式继承

  寄生式继承是与原型式继承紧密相关的一种思路,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。

function createAnother(original)
{
    var clone = Object(original);
    clone.sayHi = function()
    {
        console.log("hi");
    };
    return clone;
}

var person = {
    name:"Nicholas",
    friends:["Shelby","Court","Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();   //"hi"
View Code

以上是关于JavaScript语言对继承的使用的主要内容,如果未能解决你的问题,请参考以下文章

你可能不知道的JavaScript代码片段和技巧(上)

译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务

面向对象的JavaScript --- 动态类型语言

对Javascript 类原型链继承的理解

javascript 继承

javascript啥是继承