一种基于ES5的JavaScript继承
关于JavaScript继承,方式非常多,包含compile-to-javascript的语言TypeScript, CoffeeScript以及站点MDN, GitHub, Modernizr各种polyfill都给出了稳妥的实现方案。
从ES5的角度看,这当中一些方案在功能上OK,但在语义上却不尽如人意。
本人从这些方案中採取一些比較潮的思路,整理出一份方案,可实现与原生DOM类继承的风格一致,达到功能和语义兼得的效果(当然,就别再老想着99后ES3了)。
假设你的WebApp是基于ES5执行环境的,能够评估或fork此方案。
//exports Function.prototype.extends
//exports global.getPrototypeNames //基于ES5的继承实现函数
Function.prototype.extends=(function(){
function getOwnPropertyDescriptors(object){
return Object.getOwnPropertyNames(object).reduce(function(pds,pn){
return pds[pn]=Object.getOwnPropertyDescriptor(object,pn),pds;
},{});
}
/**
* 继承一个类。
* 若有兴许类,则共享兴许类截至到当前的快照属性(constructor除外),
* 这些属性中的getters,setters和methods须考虑到要是通用的(如Array的那些methods)
**/
function inherits(s){
var c,p;
c=this;
if(typeof s==="function"){
p=Object.create(s.prototype,getOwnPropertyDescriptors(c.prototype));
}else{
p=c.prototype;
}
if(arguments.length>1){
Array.prototype.slice.call(arguments,1).forEach(function(s){
var pds=getOwnPropertyDescriptors(s.prototype);
delete pds.constructor;
Object.defineProperties(p,pds);
});
}
c.prototype=p;
}
return inherits;
}()); //測试准备
//~~~~~~~~~~~~~~~~~~~~~~~~
// BaseList extends Array
//~~~~~~~~~~~~~~~~~~~~~~~~
function BaseList(){
this.length=this.length;
}
BaseList.prototype.add=function(e){
return this.push(e);
};
BaseList.extends(Array); //~~~~~~~~~~~~~~~~~~~~~~~~
// ItemList extends BaseList
//~~~~~~~~~~~~~~~~~~~~~~~~
function ItemList(){
BaseList.call(this);
}
ItemList.extends(BaseList,EventTarget);
ItemList.prototype.item=function item(index){
index>>>=0;
return index<this.length?this[index]:null;
}; //~~~~~~~~~~~~~~~~~~~~~~~~
// ElementList extends ItemList
//~~~~~~~~~~~~~~~~~~~~~~~~
function ElementList(){
ItemList.call(this);
}
ElementList.extends(ItemList);
ElementList.prototype.namedItem=function namedItem(name){
var index=this.findIndex(function(elem){return elem.name===name;});
return index===-1?null:this[index];
}; //測试工具函数之获取原型链名单
var getPrototypeNames=(function(){
function typeOf(value){
return Object.prototype.toString.call(value).slice(8,-1);
}
function isObject(value){
return typeof value==="object"&&value!==null||typeof value==="function"
}
function constructorNameOf(proto){
return typeof proto.constructor==="function"?proto.constructor.name:typeOf(proto)
}
function getPrototypeNames(object){
var names,proto;
names=[];
proto=Object.getPrototypeOf(object);
while(isObject(proto)){
names.push(constructorNameOf(proto));
proto=Object.getPrototypeOf(proto)
}
return names;
}
return getPrototypeNames;
}()); //运行測试
var list=new ElementList(); console.dir(list);
console.log("list: "+getPrototypeNames(list).join(" > ")); list.push(document.documentElement);
list.push(document.head);
console.assert(list.item(1)===document.head,"The second item of list is document.head");
一种基于ES5的JavaScript继承的更多相关文章
- JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)
JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...
- javascript继承的三种模式
javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...
- javascript继承(五)—prototype最优两种继承(空函数和循环拷贝)
一.利用空函数实现继承 参考了文章javascript继承—prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...
- javascript继承—prototype最优两种继承(空函数和循环拷贝)
一.利用空函数实现继承 参考了文章javascript继承-prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...
- javaScript继承的几种实现方式?
js继承总共分成5种,包括构造函数式继承.原型链式继承.组合式继承.寄生式继承和寄生组合式继承. 构造函数式继承 首先来看第一种,构造函数式继承,顾名思义,也就是利用函数去实现继承:构造函数继承,使用 ...
- javascript继承之学习笔记
今天记录一下学习javascript的继承. 继承基本上是基于“类”来说的,而javascript中并不存在真正的类,所以就出现了各种模拟“类”的行为,然后就堂而皇之的使用起了类的概念.这里不谈“类” ...
- JavaScript 继承小记
面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过“类”(class) ...
- 一篇文章图文并茂地带你轻松学完 JavaScript 继承
JavaScript 继承 在阅读本文章之前,已经默认你了解了基础的 JavaScript 语法知识,基础的 ES6 语法知识 . 继承种类 简单的继承种类可以分为 构造函数继承 原型链继承 clas ...
- 关于JavaScript继承的那些事
在JavaScript中,对象的创建可以脱离类型(class free),通过字面量的方式可以很方便的创建出自定义对象. 另外,JavaScript中拥有原型这个强大的概念,当对象进行属性查找的时候, ...
随机推荐
- Failed to create the Java Virtual Machine
启动Zend Studio时出现Failed to create the Java VIrtual Machine 解决办法如下.打开安装目录下的ZendStudio.ini配置文件,作如下修改: 说 ...
- Vue-Socket.io
github地址:https://github.com/MetinSeylan/Vue-Socket.io 安装: npm install vue-socket.io -S 注册: import Vu ...
- CVE-2013-2729 Adobe Reader和Acrobat 数字错误漏洞
这个洞是在论坛里看到的,感觉很有意思,来学习一下.个人感觉IE或者说是浏览器的洞和Adobe洞都是比较难调的,主要是有大量的类难以摸清之间的关系. 这个洞是一个整数溢出的洞,这个不是重点.重点是利用的 ...
- Spring Boot使用JavaMailSender发送邮件
http://www.cnblogs.com/wxc-xiaohuang/p/9532631.html https://blog.csdn.net/icannotdebug/article/detai ...
- android拾遗——Android Intent详解
一. Intent 作用 Intent 是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯.比如说调用startActivity()来 ...
- 自定义Adapter为什么会重复多轮调用getView?——原来是ListView.onMeasure在作祟
相信很多人在使用自定义Adapter的时候都遇到这样的问题: 假设Adapter数据源中只有30个Item,理论上每显示一个新的Item的时候就会调用一次getView,均显示一次的话是要调用getV ...
- 【LOJ】#2306. 「NOI2017」蔬菜
题解 从后往前递推 如果我们知道了第i天的最优方案和第i天选择的蔬菜,加入第i天选择的蔬菜数量为S,我们只需要减去最小的S - (i - 1) * M 个蔬菜即可 所以我们只要求出最后一天的蔬菜选择 ...
- R语言实战(八)广义线性模型
本文对应<R语言实战>第13章:广义线性模型 广义线性模型扩展了线性模型的框架,包含了非正态因变量的分析. 两种流行模型:Logistic回归(因变量为类别型)和泊松回归(因变量为计数型) ...
- NetworkX 使用(三)
官方教程 博客:NetworkX NetworkX 使用(二) Introduction to Graph Analysis with NetworkX %pylab inline import ne ...
- PHP接入支付宝支付
创建应用 使用支付宝账号登录开放平台创建应用,应用创建成功之后可以得到APPID等相关信息 接着需要设置RSA密钥,可以使用蚂蚁金服开放平台提供的生成工具,生成完密钥需在开放平台中填写. 代码接入 引 ...