破解 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 ...
随机推荐
- 2018-2019-1 20189203《Linux内核原理与分析》第四周作业
第一部分 课本学习 内核版本号:Linux内核自2013年12月起,就以A.B.C.D的方式命名.A和B变得无关紧要,C是内核的真实版本.每一个版本的变化都会带来新的特性,如内部API的变化等,改动的 ...
- Fiddler和PostMan的使用例子和下载
一.Fiddler:先下个 1.先讲下Get请求:很简单就一图示意: 然后再讲下POST:举个例子 请求主体的内容: User-Agent: FiddlerContent-Type: applicat ...
- jenkins配置工程目录-启动case
1.我们在python里面编辑的脚本可以正常跑,但是在cmd里面跑就不行了,找不到自己定义的方法模块,这个时候我们要搞个环境变量 name : PYTHONPATH val : 工程目录路劲 ...
- 查询oracle数据字典,并对应出hive的数据类型
SQL开始 select t2.owner||'.'||t2.TABLE_NAME 源表名, 'dl_{0}_seq.'||'tt_{1}_'||lower(t2.table_name) hive表名 ...
- python多线程学习三
本文希望达到的目标: 1.服务器端与线程池 (实例demo) 2.并发插入db与线程池(实例demo) 3.线程池使用说明 4.线程池源码解析 一.基于socket的服务器与线程池连接. 1.在i7 ...
- Python之猴子补丁
1.在运行时,对属性,方法,函数等进行动态替换 2.其目的往往是为了通过替换,修改来增强,扩展原有代码的能力 #test2.py class Person: def get_score(self): ...
- 从AST编译解析谈到写babel插件
之前一直在掘金上看到一些关于面试写babel插件的文章,最近也在学,以下就是学习后的总结. 关键词:AST编译解析, babel AST编译解析 AST[维基百科]:在计算机科学中,抽象语法树(Abs ...
- 设置div 高度 总结
如果将div 的height 设置为固定的像素值,在不同分辨率的显示屏上,会看到div 在浏览器上的高度不一致.可以以百分比的形式设置div 的高度.注意,这个百分比是针对div 的上一层标签而言的, ...
- Mysql 书写语句时避免出现关键字导致报错 关键字大全
ADD ALL ALTER ANALYZE AND AS ASC ASENSITIVE BEFORE BETWEEN BIGINT BINARY BLOB BOTH BY CALL CASCADE C ...
- 判断(if)语句
目标 开发中的应用场景 if语句体验 if语句进阶 综合应用 一 开发中的应用场景 转换成代码 判断的定义 如果 条件满足,才能做某件事 如果 条件不满足,就做另外一件事,或者什么也不做 判断语句 又 ...