总体分为四大类:利用空对象作为中介继承、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(原型)继承的更多相关文章
-
【09-23】js原型继承学习笔记
js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...
-
JS原型继承与类的继承
我们先看JS类的继承 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...
-
js原型继承四步曲及原型继承图
一:js原型继承四步曲 //js模拟类的创建以及继承 //动物(Animal),有头这个属性,eat方法 //名字这个属性 //猫有名字属性,继承Animal,抓老鼠方法 //第一步:创建父类 fun ...
-
JS原型继承和类式继承
前言 一个多月前,卤煮读了一篇翻译过来的外国人写的技术博客.此君在博客中将js中的类(构造)继承和原型继承做了一些比较,并且得出了结论:建议诸位在开发是用原型继承.文中提到了各种原型继承的优点,详细的 ...
-
关于js原型继承
js的每个类都有一个prototype对象 访问对象的属性时,会先访问到对象自身是否有定义这个属性 如果没有定义,就会去访问对象所属类型的prototype对象是否有此属性 原型继承就是把类型的pro ...
-
js原型继承
原型链: Object(构造函数) object(类型(对象)) var o = {}; alert(typeof o); //结果是object alert(typeof Object); //结果 ...
-
js原型继承深入
js采用原型继承来实现类的派生,但是原型链再深入点,我们又知道多少呢,现在不妨往下看: 先来一个原型继承: var M1 = function() { this.param = "m1's ...
-
前端面试题总结二(js原型继承)
今天这篇文章整理了JS原型和继承的一些知识点,面试的时候 基!本!都!会!问!还不快认真阅读下文,看看你还有哪些知识点需要掌握吧~ 1.原型链 基本思想:利用原型让一个引用类型继承另外一个引用类型的 ...
-
JS 原型继承的几种方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
-
JS 原型 &; 继承
理解原型链 先看看http://www.ituring.com.cn/article/56184和http://www.cavabiao.com/prototype-and-inherit-of-ja ...
随机推荐
-
Oracle Deadlock / 死锁 处理
Get the directory of alert log sqlplus / as sysdba show parameters udmp SQL> show parameters dump ...
-
无需部署的轻量级数据库—SQLLite,使用Demo
当有程序需要保存轻量数据,而又烦躁序列化到本地的不便,轻量级数据库—SQLLite是一个很好的选择,只需引用System.Data.SQLite.DLL,无需部署数据库,便可像拥有数据库一样保存数据, ...
-
ASP.NET MVC- Controllers and Routing- Controller Overview
In this tutorial, Stephen Walther introduces you to ASP.NET MVC controllers. You learn how to create ...
-
15_Python模块化编程_Python编程之路
之前跟大家讲的是一些python的数据基础,从这篇文章开始,我们开始正式学习python的模块化编程 下面我们解释一下什么叫做模块 之前已经讲过怎么去定义一个方法,如果你是用python交互器(自带交 ...
-
platform模块
import platform ''' python中,platform模块给我们提供了很多方法去获取操作系统的信息 如: import platform platform.platform() #获 ...
-
Microsoft Office Access数据库或项目包含一个对文件“dao360.dll”版本5.0.的丢失的或损坏的引用。
今天使用 office 2007 access 打开 2003 的数据库中的表时候,提示这个错误.经过搜索,发现是没有 dao360.dll 的问题. 在 https://cn.dll-files.c ...
-
NodeMCU学习(一) : 开始之前的准备
安装Aduino开发环境 在官网中下载Arduino开发环境,或者在网盘中下载: 网盘地址: https://pan.baidu.com/s/1OjMhYgKOYW69YC2dEwFgyw: 提取码: ...
-
在ASP.NET MVC4中实现同页面增删改查,无弹出框02,增删改查界面设计
在上一篇"在ASP.NET MVC4中实现同页面增删改查,无弹出框01,Repository的搭建"中,已经搭建好了Repository层,本篇就剩下增删改查的界面了......今 ...
-
mysql中如何删除表上的索引?删除索引?
需求描述: 今天在做SQL的优化的时候,想要把mysql中某个表上的索引删除掉,突然忘记语法了,找到帮助,在此记录下 操作过程: 1.查看表上的索引 show index from ti_o_sms; ...
-
删除RAC集群节点
删除GRID集群节点:参考oracle database 11g RAC手册(第二版) 目前GRID集群中节点信息:[grid@node1 ~]$ olsnodesnode1node2node3nod ...