1)原型链

  ①原型链示例

function Shape() {
    this.name = 'shape';
    this.toString = function(){
        return this.name;
    }
}

function TwoDshape () {
    this.name = '2D shape';
}

function Triangle (side,height) {
    this.name = 'Triangle';
    this.side = side;
    this.height = height;
    this.getArea = function () {
        return this.side * this.height / 2;
    }
}

TwoDshape.prototype = new Shape();
Triangle.prototype = new TwoDshape();   //用new新建对象实体,并赋值覆盖该对象的原型
TwoDshape.prototype.constructor = TwoDshape;
Triangle.prototype.constructor = Triangle; 

var my = new Triangle(5,10);
my.getArea();       
console.log(my.toString());//继承的方法,具体步骤(遍历my对象属性没有找到,接着查看my.__proto__所指向的对象,即new TwoDshape()创建的实体,
//依然没找到,又继续查找该实体的__proto__所指向的对象,即new Shape()所创建的实体,找到toString方法,并在my对象中被调用,this指向my)

//通过instanceof操作符,我们可以验证my对象同时是上面三个构造器的实例
my instanceof Shape;          //true
my instanceof  TwoDShape;     //true
my instanceof Triangle;      //true

//我们也可以用其他两个构造器来创建对象,用new TwoDshape()所创建的对象也可以获得继承自Shape()的toString()方法var td = new TwoDshape();td.constructor === TwoDshape;   //true;td.toString();          // 2D shape

var s = new Shape();s.constructor === shape;    // true;

②将共享属性迁移到原型中去

function Shape(){this.name='shape'}//使用new Shape()新建对象,每个实体都有全新的属性并占用独立空间
function Shape(){};Shape.prototype.name='shape';//属性移到原型后,使用new新建对象时,不再含自己独立的这个属性

2)只继承于原型

Triangle.prototype=Shape.prototype;//减少继承方法的查询步骤
Triangle.prototype.name='Triangle';//修改子对象原型后父对象原型也随即被改,即再new Shape()新建对象时,新对象name为‘Triangl

  ②临时构造器——new F()

function Shape() {}
Shape.prototype.name = "shape";
Shape.prototype.toString = function () {
    return this.name;
}

function TwoDshape() {}
var F = function () {};
F.prototype = Shape.prototype;
TwoDshape.prototype = new F();
TwoDshape.prototype.constructor = TwoDshape;
TwoDshape.prototype.name = '2D shape';

function Triangle(side, height) {
    this.side = side;
    this.height = height;
}
var F = function () {};
F.prototype = TwoDshape.prototype;
Triangle.prototype = new F();
Triangle.prototype.constructor = Triangle;
Triangle.prototype.name = 'Triangle';
Triangle.prototype.getArea = function () {
    return this.side * this.height / 2;
}

var my = new Triangle (5,10);
alert(my.getArea());

//通过这种方法,我们仍然能保持住原型链my._proto_ === Triangle.prototype;              //truemy._proto_.constructor === Triangle;            //truemy._proto_._proto_ === TwoDshape.prototypr;        //truemy._proto_._proto_._proto_.constructor === Shape;_    //true

//并且父对象的属性不会被子对象覆盖:var s = new Shape();s.name;    // shape

//calling toString()"I am a" + new TwoDshape();     //I am a 2D shape   
                         

3)uber—子对象访问父对象的方式

function Shape(){}
Shape.prototype.name='shape';
Shape.prototype.toString=function(){
  var const = this.constructor;  return const.uber     ? this.const.uber.toString() + ',' + this.name     : this.name;}
function TwoDShape(){}
var F=function(){}
F.prototype=Shape.prototype;
TwoDShape.prototype=new F();
TwoDShape.prototype.constructor=TwoDShape;
TwoDShape.uber=Shape.prototype;
TwoDShape.prototype.name='2D shape';
function Triangle(side,height){
  this.side=side;
  this.height=height;
}
var F=function(){}
F.prototype=TwoDShape.prototype;
Triangle.prototype=new F();
Triangle.prototype.constructor=Triangle;
Triangle.uber=TwoDShape.prototype;
Triangle.prototype.name='triangle';
Triangle.prototype.getArea=function(){return this.side*this.height/2};
var my=new Triangle(5,10)
console.log(my.toString());//shape,2D shape,triangle

4)将继承部分封装成函数

function extend (Child,Parent) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;
}

extend(TwoDsgape,Shape);
extend(Triangle,TwoDshape);

5)属性拷贝

/*属性拷贝执行的是对象原型的逐一拷贝,而非简单的原型链查询。
  所以需要特别注意的是:
    这种方法仅适用于包含基本数据类型的对象,
    所有的对象类型(包括函数和数组)都是不可复制的,
    因为他们只支持引用传递
*/

function extend2(Child,Parent){
    var p = Parent.prototype;
    var c = Child.prototype;
    for(var i in p){
        c[i] = p[i];
    }
    c.uber = p ;
}

6)小心处理引用拷贝

var A=function(){},B=function(){};
A.prototype.stuff=[1,2,3];
A.prototype.name='a';
extend2(B,A);//让B继承A使用方法二
B.prototype.name+='b';//ab,A.prototype.name依然为a,因为拷贝的是值
B.prototype.stuff.push(4);//此时A和B原型上的stuff同时被修改,因为拷贝的是应用
B.prototype.stuff=['a','b','c']//如果完全重写事情就不一样了,A为原来,B为新的

7)对象之间的继承(不使用构造器)

function extendCopy (p) {
    var c = {};
    for (var i in p){
        c[i] = p[i];
    }
    c.uber = p;
    return c;
}

var shape ={
    name = 'shape',
    toString :function () {
        return this.name;
    }
}

var twoDee = extendCopy(shape);
twoDee.name = '2D shape';
twoDee.toString = function () {
    return this.uber.toString() + ',' + this.name;
}

//下面我们让triangle对象继承一个2D图形对象
var triangle = extendCopy(twoDee);
triangle.name = 'Triangle'
triangle.getArea = function () {
    return this.side * this.height / 2;
}

//使用triangle
triangle.side = 5;
triangle.height = 10;
triangle.getArea();          

triangle.toString();        // shape,2D shape,Triangle

8)深拷贝(当遇到对象类型时,再次调用拷贝)

function deepCopy(p,c){
    c = c || {};
    for (var i in p){
        if(p.hasOwnProperty(i)){
            if(typeof p[i] === 'object'){
                c[i] = Array.isArray(p[i]?[]:{});
                deepCopy(p[i],c[i]);
            }else{
                c[i] = p[i]
            }
        }
    }
    return c;
}

var parent = {
    numbers:[1,2,3],
    letters:['a','b','c'],
    obj:{
        prop : 1
    },
    bool : true
};

//我们分别用深拷贝和浅拷贝测试一下,就会发现两者的不同。
//在深拷贝中,对对象的numbers属性进行更新不会对原对象产生影响。

var mydeep = deepCopy(parent);
var myshallow = extendCopy(parent);

mydeep.numbers.push(4,5,6);
mydeep.numbers     //[1,2,3,4,5,6]
parent.numbers     //[1,2,3]

myshallow.numbers.push(10);
myshallow.numbers   //[1,2,3,10]
parent.numbers      //[1,2,3,10]

9)object()(用object函数来接受父对象,并返回一个以该对象为原型的新对象)

function object(o){
  var n;
  function F(){}
  F.prototype=o;
  n=new F();
  n.uber=o;
  return n;
}//这个函数与extendcopy基本相同

10)原型继承与属性拷贝的混合应用

function objectplus(o,stuff){
  var n;
  function F(){}
  F.prototype=o;
  n=new F();
  n.uber=o;
  for(var i in stuff){n[i]=stuff[i]}
  return n;
}//两对象o用于继承,stuff用于拷贝方法与属性

11)多重继承(一个对象中有不至一个父对象的继承)

function multi(){
  var n={},stuff,j=0,len=arguments.length;
  for(j=0;i<len;j++){
    stuff=arguments[j];
    for(var i in stuff){n[i]=stuff[i]}
  }
  return n;
}//内层循环用于拷贝属性,外层循环用于遍历多个父对象参数,若有相同属性后面替代之前

12) 寄生式继承

13)构造器借用

待续...

(知识点)JavaScript继承的更多相关文章

  1. javascript继承的三种模式

    javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...

  2. javascript继承机制的设计思想(ryf)

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

  3. 【读书笔记】javascript 继承

    在JavaScript中继承不像C#那么直接,C#中子类继承父类之后马上获得了父类的属性和方法,但JavaScript需要分步进行. 让Brid 继承 Animal,并扩展自己fly的方法. func ...

  4. 图解JavaScript 继承

    JavaScript作为一个面向对象语言,可以实现继承是必不可少的,但是由于本身并没有类的概念(不知道这样说是否严谨,但在js中一切都类皆是对象模拟)所以在JavaScript中的继承也区别于其他的面 ...

  5. C#基础总结之八面向对象知识点总结-继承与多态-接口

    .方法深入讲解(返回值,形参与实参) 方法 public int getName(int i,int j) { int sum = i + j; return sum; } .利用泛型存储对象数据 . ...

  6. JavaScript强化教程——Cocos2d-JS中JavaScript继承

    javaScript语言本身没有提供类,没有其它语言的类继承机制,它的继承是通过对象的原型实现的,但这不能满足Cocos2d-JS引擎的要求.由于Cocos2d-JS引擎是从Cocos2d-x演变而来 ...

  7. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  8. javascript继承(六)—实现多继承

    在上一篇javascript继承—prototype最优两种继承(空函数和循环拷贝)(3) ,介绍了js较完美继承的两种实现方案,那么下面来探讨一下js里是否有多继承,如何实现多继承.在这里可以看看j ...

  9. javascript继承(五)—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承—prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

  10. javascript继承(四)—prototype属性介绍

    js里每一个function都有一个prototype属性,而每一个实例都有constructor属性,并且每一个function的prototype都有一个constructor属性,这个属性会指向 ...

随机推荐

  1. Android之万能播放器解码框架Vitamio的介绍及使用

    一.简介 Vitamio能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在Android 与 iOS 上跨平台支持 MMS, RTSP, R ...

  2. Octave Tutorial(《Machine Learning》)之第一课《数据表示和存储》

    Octave Tutorial 第一课 Computation&Operation 数据表示和存储 1.简单的四则运算,布尔运算,赋值运算(a && b,a || b,xor( ...

  3. koa中间件系统原理及koa+orm2实践。

    koa是由 Express 原班人马打造的新的web框架.套用其官方的说法:Koa 应用是一个包含一系列中间件 generator 函数的对象. 这些中间件函数基于 request 请求以一个类似于栈 ...

  4. golang socket 分析

    socket:tcp/udp.ip构成了网络通信的基石,tcp/ip是面向连接的通信协议 要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭 在通信过程 ...

  5. Win10 UWP开发系列:开发一个自定义控件——带数字徽章的AppBarButton

    最近有个项目有一个这样的需求,在文章浏览页底部有几个AppBarButton,其中有一个是评论按钮,需要在评论按钮上显示一个红色数字,类似微信的新消息提醒: 这种设计在iOS和Android平台都是很 ...

  6. java学习笔记 --- 数组

    一.Java的内存分配   A:栈内存: 存储局部变量,只要是在方法中定义的变量都是局部变量.一旦变量的生命周期结束该变量就被释放.   B:堆内存: 存储所有new出来的,及实体(对象),每一个实体 ...

  7. java学习笔记----数据类型,变量,常量

    一.数据类型 1.基本类型(8种,又称内置数据类型).6种数字类型(byte,short,int,long,float,double),一种字符型(char),一种布尔类型(boolean). byt ...

  8. iOS开发之CALayer

    1.         概述 在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView,其实UIView之所以能显示在屏幕 ...

  9. datagrid-detailview.js easyui表格嵌套

    datagrid-detailview.js easyui表格嵌套

  10. 关于Android开发的几点建议

    绝不要在UI线程中做数据处理的工作,这会让你的app变慢,带来极差的用户体验. 要按照google发布的Design指导意见来设计app,比如一个holo主题app会给用户带来更好的用户体验. 不要复 ...