破解 JS(原型)继承
总体分为四大类:利用空对象作为中介继承、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 ...
随机推荐
- larave----------通过composer.json下载laravel包----barryvdh/laravel-debugbar
1.去Packagist网站https://packagist.org/packages/barryvdh/laravel-debugbar#dev-master找到
- #WEB安全基础 : HTTP协议 | 0x3 TCP三次握手和DNS服务
TCP三次握手精准无误地把数据送达目标处,TCP协议把数据包送出去后,向对方确认是否成功发送,握手过程中使用了TCP的标志(flag)——SYN和ACK 请看图 若握手中断,TCP协议再次从同样顺序发 ...
- SQL Server 2008 报表服务入门【转】
转http://www.cnblogs.com/YZDONET/archive/2012/08/17/2644711.html 概述 上周,Tim与我们分享了SQL Server 2008 报表服务的 ...
- codeforces 985B Switches and Lamps
题意: 有n个开关,m盏灯. 一个开关可以控制多个灯,一旦一个灯开了之后,之后再对这个灯的操作就没用了. 问是否存在一个开关,去掉了这个开关之后,按下其它开关之后所有的灯还是亮的. 思路: 首先统计每 ...
- FTR-B3GA003Z-信号继电器
IC名称:B3GA003Z 数据手册:链接:https://pan.baidu.com/s/1MNe-fcKNAnuXyRLxhfUhjA 密码:6mo2 芯片自拍照: 封装尺寸以及引脚说明: 信号电 ...
- js-cookie的用法
cookie的作用无需多言,自己封装一个cookie,不停地复制黏贴页颇为麻烦,在这里,有npm为我们封装好的插件js-cookie: https://www.npmjs.com/package/js ...
- Beaglebone板子修改usb连接时的默认IP192.168.0.2
首先除了有个USB线外,你还需要一个USB转串口的线(目的是防止修改错误,无法使用原来的usb的IP地址登陆,心大的可以跳过这步直接进入重点),串口线连接方法如下图: 将USB以及串口和PC机相连 ...
- 论文笔记【一】Chinese NER Using Lattice LSTM
论文:Chinese NER Using Lattice LSTM 论文链接:https://arxiv.org/abs/1805.02023 论文作者:Yue Zhang∗and Jie Yang∗ ...
- 剑指offer(22)从上往下打印二叉树
题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 题目分析 从下打印就是按层次打印,其实也就是树的广度遍历. 一般来说树的广度遍历用队列,利用先进先出的特点来保存之前节点,并操作之前的 ...
- Java 泛型方法、泛型类、通配符、通配符上下限
泛型方法 泛型方法定义规则: 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前. 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开.一个泛型 ...