破解 JS(原型)继承
来源:互联网 发布:sqlserver rds客户端 编辑:程序博客网 时间:2024/05/18 15:25
总体分为四大类:利用空对象作为中介继承、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.prototypechild.prototype = Object.create(parent.prototype);// 直接修改默认的 child.prototypeObject.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(原型)继承
- JS:原型、原型链、继承
- js 原型(prototype) 继承相关
- js 原型继承
- js原型、继承
- JS原型继承实例
- js原型、继承
- js原型、继承
- js原型、继承
- js原型、继承
- js的原型继承
- JS 原型继承
- 再谈js原型继承
- js原型、继承
- 【JS】原型链继承
- js原型继承
- js原型、继承
- js原型、继承
- 使用布局管理器管理布局
- Deep Bilateral Learning for Real-Time Image Enhancement
- 什么是RTOS系统定义分析
- MEC —— 优化内存与速度的卷积计算
- docker 简介
- 破解 JS(原型)继承
- Android EventBus框架入门
- HDU 4511 小明系列故事——女友的考验 (AC自动机 + dp)
- 三级菜单案例
- wireshark如何抓取本机包
- 【永久 | 一次性解决】Intellij IDEA maven 老是自动跳到1.5的JDK
- c++各种进制间的转换
- Java学习笔记(二)之Java的数据类型
- eclipse下通过jdbc连接各个类型的数据库