Javascript继承,再谈
说到Javascript的继承,相信只要是前端开发者都有所了解或应用,因为这是太基础的知识了。但不知各位有没有深入去理解其中的玄机与奥秘。今本人不才,但也想用自己的理解来说一说这其中的玄机和奥秘。
一、类继承的发展吏
- function实现的继承
function的继承是完全模仿了OOP的编程思想。实现的是类的继承
- object.create实现的继承
用object.create来修改其原型
- es6的继承
增加了class来模拟OOP的继承实现。上述两种继承实现,他都还是支持的。
二、各时期类继承的实现
- function继承方式的实现(OOP)
function Animate(name){
this.name = name;
}
Animate.prototype.getName = function(){
return this.name;
} function Dog(name){
Animate.apply(this,arguments);
this.leg = 4;
}
Dog.prototype = Inherit(Animate, Dog);
Dog.prototype.say = function(){
return 'wang';
} //function模式的继承
function Inherit(parent, child){
//创建一个无原型方法的类
function f(){}
f.prototype = parent.prototype; //将父对象的原型赋给临时对象
f.prototype.constructor = child; //将子类构造函数绑定到 临时对象的 prototype原型上,保持子类构造函数与prototype上的一致。
return new f(); //执行了f的构造函数,而没有执行prototype.constructor指向的构造函数
} var dog = new Dog('dog');
console.log('getName:' + dog.getName()); //dog
console.log("say:" + dog.say()); //wang
console.log( 'dog instanceof Animate:' + (dog instanceof Animate)); //true
console.log( 'dog instanceof Animate: ' + (dog instanceof Dog)); //true
OOP方式的继承实现网上有很多种,如:原型链,实现、组合、寄生组合继承等。上述实现为寄生组合继承在,算比较通用且完美的一种方案了。
- object.create实现继承
这是一个升级版本的类式继承,需要了解object.create方法。Object.create(proto, [propertiesObject]),其中proto是新创建对象的原型对象,而propertiesObject是可选的,要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是原型链接上的属性)。
我们还需要了解的方法:Object.setPrototypeOf(内部原型的写方法);Object.getPrototypeOf(内部原型的读方法)。内部原型:[[prototype]] == proto
上述继承代码的改造后
function Animate(name){
this.name = name;
}
Animate.prototype.getName = function(){
return this.name;
} function Dog(name){
Animate.apply(this,arguments);
this.leg = 4;
}
Inherit(Animate, Dog); //调用点改造
Dog.prototype.say = function(){
return 'wang';
}
//继承实现方法改造
function Inherit(parent, child){
child.prototype = Object.create(parent.prototype); //create实现parent上的原型复制
child.prototype.constructor = child; //将构造函数指回子类
} var dog = new Dog('dog');
console.log('getName:' + dog.getName()); //dog
console.log("say:" + dog.say()); //wang
console.log( 'dog instanceof Animate:' + (dog instanceof Animate)); //true
console.log( 'dog instanceof Animate: ' + (dog instanceof Dog)); //true
2.1 对prototype的尝试
上述示例中用了Object.create方法创建一个对象,然后再赋值给Prototype,而为什么不用Object.setPrototypeOf方法直接改变其Prototype的值呢。原因摘录来源于MDN:
由于现代 JavaScript 引擎优化属性访问所带来的特性的关系,更改对象的 [[Prototype]]在各个浏览器和 JavaScript 引擎上都是一个很慢的操作。其在更改继承的性能上的影响是微妙而又广泛的,这不仅仅限于 obj.proto = ... 语句上的时间花费,而且可能会延伸到任何代码,那些可以访问任何[[Prototype]]已被更改的对象的代码。如果你关心性能,你应该避免设置一个对象的 [[Prototype]]。相反,你应该使用 Object.create()来创建带有你想要的[[Prototype]]的新对象。
对象继承的实现:
var animate = {
name: "name"
};
Object.setPrototypeOf(animate,{
getName: function(){
return this.name;
}
}); var dog = {
leg: 4
};
Object.setPrototypeOf(dog,{
say: function(){
return 'wang';
}
});
Object.setPrototypeOf(Object.getPrototypeOf(dog),Object.getPrototypeOf(animate)); console.log('getName:' + dog.getName()); //dog
console.log("say:" + dog.say()); //wang
三、ES6类继承的实现
es6对类继承提供了原生的支持,这让Javascript更像后端语言了,简单使用如下:
class Animate{
constructor(name){
this.name = name
}
getName(){
return this.name;
}
} class Dog extends Animate{
constructor(name){
super(name);
this.leg = 4;
}
say(){
return "wang";
}
}
var dog = new Dog('dog');
console.log('getName:' + dog.getName()); //dog
console.log("say:" + dog.say()); //wang
console.log( 'dog instanceof Animate:' + (dog instanceof Animate)); //true
console.log( 'dog instanceof Animate: ' + (dog instanceof Dog)); //true
四、总结及疑问
经过本文梳理,你是否发现Javascript的类继承实现越来越简单,更接近于Java,.net这类静态编译语言了,或许这就是所谓的万物归一的哲学道理。但在此还是存在一个极大的疑问:Object.setPrototypeOf方法在MDN不建议使用,说是更改内部的[[prototype]]属性存在性能问题 和 影响。不知道其影响为何,望大神们指定。
Javascript继承,再谈的更多相关文章
- JavaScript之再谈回调与闭包
前些阵子写了几篇关于回调和闭包的博文,感觉自己都是似懂非懂,最近在项目中又碰到了类似的情况,故在此咱们来重弹js中的回调与闭包. 先说说回调: 百度百科: 回调函数就是一个通过函数指针调用的函数.如果 ...
- JavaScript:再谈Tasks和Microtasks
JavaScript是单线程,也就是说JS的堆栈中只允许有一类任务在执行,不可以同时执行多类任务.在读js文件时,所有的同步任务是一条task,当然了,每一条task都是一个队列,按顺序执行.而如果在 ...
- 再谈javascript原型继承
Javascript原型继承是一个被说烂掉了的话题,但是自己对于这个问题一直没有彻底理解,今天花了点时间又看了一遍<Javascript模式>中关于原型实现继承的几种方法,下面来一一说明下 ...
- 再谈javascriptjs原型与原型链及继承相关问题
什么是原型语言 只有对象,没有类;对象继承对象,而不是类继承类. “原型对象”是核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己创建时和运行时定义的属性,而且可以 ...
- 再谈JavaScript的数据类型问题
JavaScript的数据类型问题已经讨论过很多次了,但许多人还有许多书仍然沿用着错误的.混乱的一些观点,所以就再细讲一回. 提及这个讨论的原因在于argb同学在我的MSN博客上的一段回复,又更早的起 ...
- lesson 4 再谈继承多态,抽象类和接口
再谈多态,抽象类和接口 上一次博客已经概念性的概述了继承多态,抽象类和接口,这次来具体的谈一谈他们之间的联系和需要注意的地方. 一.继承和多态:Inheritance (继承) & Polym ...
- Java继承之再谈构造器
目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...
- 浅谈javascript继承体系
最近做web项目,接触了jquery等框架,虽然使用方便,但是还是想学习下Javascript,今天分享下最近对js原型继承的理解,不足之处欢迎指正. 一.构造器的原型属性与原型对象 刚接触js时通常 ...
- 再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结
这篇是对angularJS的一些疑点回顾,是对目前angularJS开发的各种常见问题的整理汇总.如果对文中的题目全部了然于胸,觉得对整个angular框架应该掌握的七七八八了.希望志同道合的通知补充 ...
- 再谈js对象数据结构底层实现原理-object array map set
如果有java基础的同学,可以回顾下<再谈Java数据结构—分析底层实现与应用注意事项>:java把内存分两种:一种是栈内存,另一种是堆内存.基本类型(即int,short,long,by ...
随机推荐
- HOW TO LINK THE TRANSACTION_SOURCE_ID TO TRANSACTION_SOURCE_TYPE_ID
In this Document Goal Solution References APPLIES TO: Oracle Inventory Management - Version 11 ...
- Java反编译工具(Java Decompiler)
Java Decompiler是一种非常实用的JAVA反编译工具,可以对整个jar包进行反编译,也可以将其集成到eclipse上,非常方便的根据class文件的源码.,官网地址http://jd.be ...
- css左侧固定宽度右侧自适应
左侧固定宽,右侧自适应屏幕宽: 左右两列,等高布局: 左右两列要求有最小高度,例如:200px;(当内容超出200时,会自动以等高的方式增高) 要求不用JS或CSS行为实现: 仔细分析试题要求,要达到 ...
- linux 下使用 tc 模拟网络延迟和丢包
1 模拟延迟传输简介 netem 与 tc: netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块.该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带 ...
- ionic1 打包过程 常用命令行
ionic start myapp myapp是项目名字 ionic start myapp --v2 ...
- CALayer的属性和使用
一.CALayer的常用属性 1.@propertyCGPoint position; 图层中心点的位置,类似与UIView的center:用来设置CALayer在父层中的位置:以父层的左上角为原点( ...
- dsd
nodeName属性 nodeName属性规定节点的名称 nodeName是只读的 元素节点的nodeName与属性名相同 属性节点的nodeName与属性名相同 文本节点nodeName始终是#te ...
- SQL遇到的问题
1.问题描述:拼接sql字符串涉及到表变量时报错. 解决办法:把表变量的定义一同放在字符串中. 2.问题描述:EF添加实体后,调用存储过程调用不到 解决办法:必须先db.SaveChanges()后 ...
- maven常见配置
maven surefire plugin 默认执行失败后,不会继续执行,需要在</configuration>中设置参数 <testFailureIgnore>true< ...
- Modelsim中使用TCL脚本编写do文件实现自动化仿真
通常我们使用Modelsim进行仿真,是通过图形界面点点点来进行操作,殊不知Modelsim完美支持TCL脚本语言及批处理命令do文件.简单来说就是从你修改完代码后到你重新编译把需要的信号拉出来查看, ...