讲js继承之前,想一想什么是继承? 生活中有很多例子,比方说继承财产,继承女朋友的前男友的前女友 ヽ(ー_ー)ノ ,这些和js继承差不多,但是有一个不一样的地方,就是继承过后,原先的人就没有了,js继承过后原先还有原先的属性。

最简单的继承 : 原型链继承(我最简单,也重要,也常见,不要因为简单看不起我,我很傲娇的   o(´^`)o

        原型链继承抓住了一个重要核心: 我指向的构造函数的实例就能访问原型的方法(没错,不需要理由谁叫我是你爸爸,我的方法给你用  ( ̄ェ ̄;)

        (爸爸更新的技术儿子享受就行了,爸爸添加的方法给儿子用)

function Wife( ){
this.say : function(){
console.log( ' 今天你也很美,比月亮还美 ' )
}
} // 生一个儿子呗
var son = new Wife() // 找到老公并且给孩子他爹发明一个方法fn,有了这个方法可以说Hello了
Wife.prototype.fn = function() {
cosole.log('Hello')
} son.fn() // 'Hello'

           (幸福生活没过多久,老公出轨,老婆和老公离婚,老婆不想找另一个男的,厉害了自己造一个,有鼻子有眼的,让他的心一直指向老婆constructor)

function Wife( ){
this.say : function(){
console.log( ' 今天你也很美,比月亮还美 ' )
}
} // 生一个儿子呗
var son = new Wife() // 新造一个老公
Wife.prototype = {
fn : function(){
console.log('老婆你最美')
},
say : '老婆最棒',
// 把心永远向着老婆
constructor : Wife
} son.fn() // '老婆你最美'

吸功大法:混入式继承 + 原型链继承 (在原型上定义一个混入式继承的方法)

function  Wife(){
name : ' 仙女 ',
age : 20
} Wife.prototype.extend(obj){
for( var key in obj ){
if( obj.hasOwnProperty(key) ){
this[ key ] = obj [ key ]
}
}
} var wugong1 = {
'qiankun': '乾坤大挪移'
} var wugong2 = {
'xuanming': '玄冥神掌'
} var son = new Wife();
son.extend(wugong1)
son.extend(wugong2)
console.log(son) // 添加了wugong1,wugong2,this指向发生了改变,指向了son这个实例对象,所以是son添加了,而不是原型添加了wugong1,wugong2

(为什么不说混入继承,混入继承就是遍历一个对象,把对象的属性一个一个赋给另一个对象,有需求的话注意深浅拷贝

构造函数借用  (缺点 : 方法必须也在构造函数里才能借用而借用过来的方法也在构造函数里,方法最好在原型上)

 function Animal(name){
this.name = name;
this.try = function (){
console.log('叫声')
}
}
function Cat(){
Animal.call(this,name);
// 自己的属性
this.age = 3;
}
var cat = new Cat();
console.log(cat) // 有自己的age属性 有继承构造函数的name ,try方法

既然上述方法有方法继承的缺陷,那么不妨试试组合继承(结合原型继承【处理方法继承】 + 构造函数借用【处理属性继承】,缺陷是执行两次超类构造函数)

// 组合继承  简单的说通过借用在构造函数里继承属性、用被继承的实例指向继承的原型来继承方法
// 组合继承不能继承被继承原型里的方法,也就是方法要写在构造函数里
function Animal(name) {
this.name = name;
this.color = '我是毛色';
}
function Cat(name) {
      // new的时候执行一次超类构造函数
Animal.call(this, name); //只继承属性
this.cry = '喵';
}
    // 又执行一次超类(被继承类)构造函数
Cat.prototype = new Animal(); // 把被继承的构造函数实例对象充当继承构造函数的原型,根据属性查找原则,不用担心获取的和原型的冲突
Cat.prototype.constructor = Cat; // 因为原型覆盖了,所以要加上constructor
Cat.prototype.action = function() { // 可以在原型上新建方法
console.log('猫步');
};
var cat = new Cat('波斯');
console.log(cat);// Cat {name: "波斯", color: "我是毛色", cry: "喵"}
console.log(cat.__proto__);// Animal {name: undefined, color: "我是毛色", constructor: Cat, action: ƒ}

道格拉斯(可不是尼古拉斯【红宝书作者】)的原型式继承【从原型直接到实例唯一的不足就是属性不能从原型上继承,因为不同实例不好改属性值,只适合继承方法】

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
<style></style>
</head>
<body>
<script>
var obj = {
name: 'zs',
friends: ['云云', '雪雪', '雨雨']
};
function object(o) {
function F() {}
F.prototype = o;
// 直接就不管构造函数与原型的联系,直接由原型继承
return new F();
}
var example1 = object(obj);
console.log(example1.friends.push('薇薇')); // 此举会改变obj这个对象,因为F.prototype = o是浅拷贝,导致以后实例受影响,这不算缺点
var example2 = object(obj);
console.log(example2.friends); // ['云云','雪雪','雨雨','薇薇']
</script>
</body>
</html>

最骚的继承 : 经典继承   var newObj =  Object.create( obj )  newObj是obj.contructor的实例,不是构造函数,也就是直接__proto__逆操作,骚的一P(其实就是原型继承的强化版)

Es5规范了上述的原型继承,给object取名create,并挂到Object上,唯一的不同之处在于还有第二个可选参数是个对象{  属性名 :  {  value :  属性值   }    },当属性名不存在添加,已经存在原型上则为覆盖。【话说浅拷贝的问题依然存在】

寄生继承(原型继承基础上用另一个函数把原型继承的实例增强后返回出去,通过增加的方法还不是在原型上,所以复用性不高)

var obj = {
name: 'zs',
friends: ['云云', '雪雪', '雨雨']
};
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function Parasitic(o) {
var newExample = object(o);
// 增强这个实例
newExample.sayHi = function() {
console.log('sayHi');
};
return newExample;
}
console.log(new Parasitic(obj));

最牛的继承 : 寄生组合继承 

function object(o){
function Fn(){}
Fn.prototype = o;
return new Fn()
}
function SuperType(name){
this.name = name;
this.colors = ['red','green','blue']
}
SuperType.prototype.sayHi()= function() {
console.log('我是超类');
}
function SubType(name,age){
SuperType.call(this,name)
this.age = age;
}
function ParaComponent(SubType,SuperType){
var p = object(SuperType.prototype);
p.consructor = SubType;
SubType.prototype = p;
}
ParaComponent(SubType,SuperType);
SubType.prototype.sayAge = function(){
console.log('sayAge');
}

 

js继承(自备水,这非常干货)的更多相关文章

  1. js继承

    js继承有5种实现方式: 继承第一种方式:对象冒充 function Parent(username){ this.username = username; this.hello = function ...

  2. js继承之call,apply和prototype随谈

    在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子: function FatherObj1() { this.sayhello = "I am jo ...

  3. js继承精益求精之寄生式组合继承

    一.混合/组合继承的不足 上一篇JS继承终于混合继承,认真思考一下,发现其还是有不足之处的: 空间上的冗余:在使用原型链的方法继承父类的原型属性(Animal.prototype)的同时,也在子类的原 ...

  4. 老生常谈--Js继承小结

    一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.net/stoy ...

  5. Js继承小结

    Js继承小结 一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.n ...

  6. js继承实现

    JS实现继承可以分为:对象冒充和原型链继承 其中对象冒充又包括:临时变量,call 和 apply 临时变量方法: function Person(name,sex){ this.name = nam ...

  7. js继承之借用构造函数继承

    我的上一篇文章介绍了,原型链继承模式.但是单纯的原型链模式并不能很好地实现继承. 一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,来自于原型中包含引用类型的值. 本来,我们没有通过原型链实现 ...

  8. js继承之原型链继承

    面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针, ...

  9. js继承的常用方法

    写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...

随机推荐

  1. Sprint boot notes

    1. spring.io 官网 2. http://javainuse.com/spring/sprboot spring boot学习资源 3. spring boot websocketss视频  ...

  2. ireport related

    http://blog.csdn.net/q326527970/article/details/7049047

  3. code1001 舒适的路线

    n次最小生成树kruskal 将所有的边排序,权值小的在前. 设排序后第i条边为路径中的最长边,那么这条路径一定是由1~i中的一些边组成 因为最高速和最低速的差尽量小,最高速确定了,最低速应尽量大. ...

  4. GlobalMemoryStatusEx获取内存

    typedef struct _MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLO ...

  5. Laravel 使用 Provider 为程序提供运行时配置服务

    需求: 配置参数存在数据库中,Model 是 aah,需要在每次运行时,程序可以在任何地方采用 config("aah.name") 的方式访问配置信息. 思路: 采用 Provi ...

  6. Ubuntu 安装配置 nginx

    作者:任明旭链接:https://www.zhihu.com/question/46241604/answer/100788789来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  7. oracle 查询死锁

    --查询死锁 select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked ...

  8. NetLink通信机制学习

    Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,在 Linux 2.4 版以后版本的内核中,几乎全部的中断过程与用户态进程的通信都是使用 netlink 套接字 ...

  9. CodeForces 688A Opponents (水题)

    题意:给定 n 行数,让你找出连续最多的全是1的个数. 析:好像也没什么可说的,那就判断一下,并不断更新最大值呗. 代码如下: #include <iostream> #include & ...

  10. (DP)To The Max --HDU -- 1081

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1081 这道题使用到的算法是:预处理+最大连续子串和 如果会做最大连续子串和,那么理解这题就相对简单一些, ...