总体分为四大类:利用空对象作为中介继承、Object.create 继承、setPrototypeOf 继承、拷贝继承

function Animal(name, age) {
this.name = name;
this.age = age;
} Animal.prototype = {
speak: function() {
console.log('my name is ' + this.name);
}
} function Cat() {
Animal.apply(this, arguments);
this.food = 'mouse';
}

一、利用空对象作为中介继承

function extend(child, parent) {
var F = function() {};
F.prototype = parent.prototype;
child.prototype = new F();
child.prototype.constructor = child;
}

F是空对象,所以几乎不占内存。这其实就是 YUI 实现继承的方法。

试一试

二、Object.create 继承

Object.create 会使用指定的原型对象和属性去创建一个新对象。

function extend(child, parent) {
// 任何一个prototype对象都有一个constructor属性,指向它的构造函数。
// 使 Cat.prototype 指向 Animal.prototype, 但他有一个副作用:Cat.prototype.constructor指向Animal
child.prototype = Object.create(parent.prototype);
// 修正 constructor
child.prototype.constructor = child;
}

试一试

疑问一:为什么不直接  child.prototype = parent.prototype; ?

  如果这样的话,child.prototype 会直接引用 parent.prototype 对象,那么当你对 child.prototype.constructor 进行赋值操作时,就把 parent.prototype.constructor 也给修改了

疑问二:为什么不用child.prototype = new parent(); ?

   new parent() 确实会创建一个关联到 child.prototype 的新对象。但如果函数 parent 有一些副作用(比如修改状态、注册到其它对象、给 this 添加属性等等)的话,会影响到 child() 的后代,后果不堪设想!

综上所诉,Object.create 是最好的选择,虽然它是创建了一个新对象替换掉了默认的对象。那有没有直接修改默认对象的方法呢?答案就是 setPrototypeOf

三、setPrototypeOf 继承

setPrototypeOf 是 ES6新增的辅助函数。下面来做一下对比

// 抛弃默认的 child.prototype
child.prototype = Object.create(parent.prototype); // 直接修改默认的 child.prototype
Object.setPrototypeOf(child.prototype, parent.prototype);

经过对比发现:如果忽略Object.create() 带来的轻微的损失(抛弃的对象需要进行垃圾回收),它比 ES6 的方法有更好的可读性。

四、拷贝继承

也是 jQuery 实现继承的方法

// 拷贝继承
function extend() {
var options, src, copy, copyIsArray, clone,
target = arguments[0] || {},
deep = false,
i = 1; if ( typeof target === 'boolean') {
deep = target; target = arguments[i] || {};
i++;
} if ( typeof target !== 'object' && !isFun(target)) {
target = {};
} // 循环一个或多个要拷贝的对象
for( ; i<arguments.length; i++ ) {
if ( (options = arguments[i]) != null ) {
for ( name in options ) {
src = target[name];
copy = options[name]; // 防止死循环
if ( target === copy ) {
continue;
} copyIsArray = isArray(copy);
if ( deep && copy && ( isPlainObject(copy) || copyIsArray ) ) {
// 深拷贝
if ( copyIsArray ) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
} target[name] = extend( deep, clone, copy );
// 防止拷贝 undefined
} else if ( copy !== undefined ) {
target[name] = copy;
}
}
}
} return target;
} function isFun(obj) {
return type(obj) === '[object Function]';
} function isPlainObject(obj) {
return type(obj) === '[object Object]';
} function isArray(obj) {
// IE8不支持
if (Array.isArray) {
return Array.isArray(obj);
} else {
return type(obj) === '[object Array]';
}
} function type(obj) {
if ( obj == null ) {
// obj + '' = 'null'/'undefined'
return false;
} return Object.prototype.toString.call(obj);
} var object1 = {
apple: 0,
banana: { weight: 52, price: 100 }
};
var object2 = {
banana: { price: 200 },
cherry: 97
}; extend(true, object1, object2);

试一试

破解 JS(原型)继承的更多相关文章

  1. 【09-23】js原型继承学习笔记

    js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...

  2. JS原型继承与类的继承

    我们先看JS类的继承 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  3. js原型继承四步曲及原型继承图

    一:js原型继承四步曲 //js模拟类的创建以及继承 //动物(Animal),有头这个属性,eat方法 //名字这个属性 //猫有名字属性,继承Animal,抓老鼠方法 //第一步:创建父类 fun ...

  4. JS原型继承和类式继承

    前言 一个多月前,卤煮读了一篇翻译过来的外国人写的技术博客.此君在博客中将js中的类(构造)继承和原型继承做了一些比较,并且得出了结论:建议诸位在开发是用原型继承.文中提到了各种原型继承的优点,详细的 ...

  5. 关于js原型继承

    js的每个类都有一个prototype对象 访问对象的属性时,会先访问到对象自身是否有定义这个属性 如果没有定义,就会去访问对象所属类型的prototype对象是否有此属性 原型继承就是把类型的pro ...

  6. js原型继承

    原型链: Object(构造函数) object(类型(对象)) var o = {}; alert(typeof o); //结果是object alert(typeof Object); //结果 ...

  7. js原型继承深入

    js采用原型继承来实现类的派生,但是原型链再深入点,我们又知道多少呢,现在不妨往下看: 先来一个原型继承: var M1 = function() { this.param = "m1's ...

  8. 前端面试题总结二(js原型继承)

    今天这篇文章整理了JS原型和继承的一些知识点,面试的时候  基!本!都!会!问!还不快认真阅读下文,看看你还有哪些知识点需要掌握吧~ 1.原型链 基本思想:利用原型让一个引用类型继承另外一个引用类型的 ...

  9. JS 原型继承的几种方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. JS 原型 & 继承

    理解原型链 先看看http://www.ituring.com.cn/article/56184和http://www.cavabiao.com/prototype-and-inherit-of-ja ...

随机推荐

  1. Hibernate查询操作

    操作前需要创建好Hibernate项目,创建项目,可参考:http://www.cnblogs.com/zhaojinyan/p/9336174.html 一下的例子是从其他贴子粘过来的(知识无国界! ...

  2. centos7安装zabbix3.0超详细步骤解析

    centos7安装zabbix3.0超详细步骤解析 很详细,感谢作者 以下是我操作的history 622 java -version 623 javac -version 624 grep SELI ...

  3. Centos开机自启动脚本的制作

    原文地址:http://www.2cto.com/os/201306/220559.html 我的一个Centos开机自启动脚本的制作   一.切换到/etc/init.d/   二.制作sh脚本 v ...

  4. 《数据仓库ETL工具箱》读书笔记

    在本书中,你将学习到以下内容: 规划&设计你的ETL系统 从多种可能的架构中选出最合适的 对实施过程进行管理 管理日常的操作 为ETL过程建立开发/测试/生产环境 理解不同的后台数 ...

  5. Porsche Piwis Tester II V14.000 with CF30 Laptop at autonumen.com

    Porsche piwis tester ii is the latest professional tester for Porshe,the most poweful diagnose and o ...

  6. SQL小结1

    #数据表的查询框架: select [all | distinct] select_list from tb_name [where 查询条件] [group by <group_by_expr ...

  7. 扩容 swap 分区

    扩容 swap 分区 题:添加一个 swap 分区在您的系统中添加一个大小为 512 MiB 的 swap 分区.当您的系统启动时,swap 分区应 该可以自动挂载.不要移除或者修改其他已经存在于您的 ...

  8. docker启动容器报错: could not synchronise with container process: not a directory

    错误现象 在运行容器时,出现以下错误 [root@localhost test]# docker run -it -d -v $PWD/test.txt:/mydir mytest fd44cdc55 ...

  9. Bootstrap3基础 table-responsive 响应式表格

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  10. 20175312 2018-2019-2 《Java程序设计》第4周学习总结

    20175312 2018-2019-2 <Java程序设计>第4周学习总结 教材学习内容总结 已依照蓝墨云班课的要求完成了第五章的学习,主要的学习渠道是PPT,和书的课后习题. 总结如下 ...