码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript语言对继承的使用

时间:2019-12-17 18:00:28      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:nbsp   none   自定义类   ola   ceo   type   情况   super   call()   

  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语言对继承的使用

标签:nbsp   none   自定义类   ola   ceo   type   情况   super   call()   

原文地址:https://www.cnblogs.com/zhonghu/p/12010083.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!