(知识点)JavaScript继承
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继承的更多相关文章
- javascript继承的三种模式
javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...
- javascript继承机制的设计思想(ryf)
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...
- 【读书笔记】javascript 继承
在JavaScript中继承不像C#那么直接,C#中子类继承父类之后马上获得了父类的属性和方法,但JavaScript需要分步进行. 让Brid 继承 Animal,并扩展自己fly的方法. func ...
- 图解JavaScript 继承
JavaScript作为一个面向对象语言,可以实现继承是必不可少的,但是由于本身并没有类的概念(不知道这样说是否严谨,但在js中一切都类皆是对象模拟)所以在JavaScript中的继承也区别于其他的面 ...
- C#基础总结之八面向对象知识点总结-继承与多态-接口
.方法深入讲解(返回值,形参与实参) 方法 public int getName(int i,int j) { int sum = i + j; return sum; } .利用泛型存储对象数据 . ...
- JavaScript强化教程——Cocos2d-JS中JavaScript继承
javaScript语言本身没有提供类,没有其它语言的类继承机制,它的继承是通过对象的原型实现的,但这不能满足Cocos2d-JS引擎的要求.由于Cocos2d-JS引擎是从Cocos2d-x演变而来 ...
- [原创]JavaScript继承详解
原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...
- javascript继承(六)—实现多继承
在上一篇javascript继承—prototype最优两种继承(空函数和循环拷贝)(3) ,介绍了js较完美继承的两种实现方案,那么下面来探讨一下js里是否有多继承,如何实现多继承.在这里可以看看j ...
- javascript继承(五)—prototype最优两种继承(空函数和循环拷贝)
一.利用空函数实现继承 参考了文章javascript继承—prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...
- javascript继承(四)—prototype属性介绍
js里每一个function都有一个prototype属性,而每一个实例都有constructor属性,并且每一个function的prototype都有一个constructor属性,这个属性会指向 ...
随机推荐
- Asp.net web api 知多少
本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...
- 关于数组和集合的冒泡排序中容易出现的IndexOutOfBoundsException
数组只能存错一种相同的数据类型,集合只能存储引用数据类型(用泛型),集合的底层就是一个可变的数组. 数组的冒泡排序: public static void arrayMaxPaiXu(int[] ar ...
- iOS开发之Xib和storyboard对比
相同点: (2)都用来描述软件界面 (2)都用Interface Builder工具来编辑 不同点: (1)Xib是轻量级的,用来描述局部的UI界面 (2)Storyboard是重量级的,用来描述整个 ...
- React文档翻译系列(二)Hello World
这是React文档翻译系列的第二篇,前一篇介绍了如何安装react,本篇主要介绍react的知识体系,掌握了基本的知识体系,才能更好的学习React. Hello World 开始React最简单的方 ...
- 玩转 SSH 目录
在做一个新的项目的时候,需要重新搭建一个项目. 于是趁着这个机会把之前学的几个框架的搭建都写一写,整理一下,同时也可以给大家一些参考.何乐而不为叻. 在这个系列中, 我将使用 IntelJ IDEA ...
- MySQL学习笔记(二)—查询
一.多表连接查询 新建两张表t_user.t_order. 1.内连接 返回满足条件的所有记录. (1)显式内连接 使用inner join关键字,在on ...
- HTML基础学习(一)—HTML
一.HTML的介绍 HTML(HyperText Markup Language)超文本标记语言,不是一种编程语言,而是一种描述性的标记语言,用于描述超文本的内容的显示,比如字体颜色或者大小 ...
- 如何高效实现扫描局域网IP、主机名、MAC和端口
近几年工作经常使用RFID识读器,智能家居网关,温湿度传感器.串口服务器.视频编码器等,一般是有串口和网口,由于现场原因一般较少使用串口,大多使用网口.连接方法是IP地址和端口,有的设备带搜索软件,有 ...
- 一次young gc耗时过长优化过程
1 问题源起 上游系统通过公司rpc框架调用我们系统接口超时(默认超时时间为100ms)数量从50次/分突然上涨到2000次/分,在发生变化时间段里我们的系统也没有做过代码变更,但上游系统的调用 ...
- Jmeter的逻辑控制器——Controller
逻辑控制器(Logic Controller) --贯穿整个Test Plan中,与各组件执行顺序没关系:目的是用于控制采样器的执行顺序. Simple Controller Simple Contr ...