浅谈javascript的原型继承


Posted in Javascript onJuly 25, 2012

请看源码:

function clone(o) { 
var F = function(){}; 
F.prototype = o; 
return new F(); 
}

首先看ext(4.1的1896行开始)的原型式继承。
var TemplateClass = function(){}; 
var ExtObject = Ext.Object = { 
chain: function (object) { 
TemplateClass.prototype = object; 
var result = new TemplateClass(); 
TemplateClass.prototype = null; 
return result; 
} 
}

这里清除了object的prototype。
再看一下jquery是怎么玩的继承。
var jQuery = function( selector, context ) { 
return new jQuery.fn.init( selector, context, rootjQuery ); 
}; 
----------------------- 
jQuery.fn = jQuery.prototype = { 
constructor: jQuery, 
init: function( selector, context, rootjQuery ) { 
----------------------- 
} 
} 
------------------- 
jQuery.fn.init.prototype = jQuery.fn;

jquery玩的就比较高,借助jQuery.fn.init来完成,但是思路一样。
司徒正美的mass里也有类似的继承,在lang_fix.js里面第17行:
create: function(o){ 
if (arguments.length > 1) { 
$.log(" Object.create implementation only accepts the first parameter.") 
} 
function F() {} 
F.prototype = o; 
return new F(); 
}

查看了一下es5的官方,找到了他的兼容补丁:
// ES5 15.2.3.5 
// http://es5.github.com/#x15.2.3.5 
if (!Object.create) { 
Object.create = function create(prototype, properties) { 
var object; 
if (prototype === null) { 
object = { "__proto__": null }; 
} else { 
if (typeof prototype != "object") { 
throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); 
} 
var Type = function () {}; 
Type.prototype = prototype; 
object = new Type(); 
// IE has no built-in implementation of `Object.getPrototypeOf` 
// neither `__proto__`, but this manually setting `__proto__` will 
// guarantee that `Object.getPrototypeOf` will work as expected with 
// objects created using `Object.create` 
object.__proto__ = prototype; 
} 
if (properties !== void 0) { 
Object.defineProperties(object, properties); 
} 
return object; 
}; 
}

上面的代码考虑的就比较全面,但是需要另外引入Object.defineProperties的补丁才行,源码相对就比较多了。
// ES5 15.2.3.6 
// http://es5.github.com/#x15.2.3.6 
// Patch for WebKit and IE8 standard mode 
// Designed by hax <hax.github.com> 
// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5 
// IE8 Reference: 
// http://msdn.microsoft.com/en-us/library/dd282900.aspx 
// http://msdn.microsoft.com/en-us/library/dd229916.aspx 
// WebKit Bugs: 
// https://bugs.webkit.org/show_bug.cgi?id=36423 
function doesDefinePropertyWork(object) { 
try { 
Object.defineProperty(object, "sentinel", {}); 
return "sentinel" in object; 
} catch (exception) { 
// returns falsy 
} 
} 
// check whether defineProperty works if it's given. Otherwise, 
// shim partially. 
if (Object.defineProperty) { 
var definePropertyWorksOnObject = doesDefinePropertyWork({}); 
var definePropertyWorksOnDom = typeof document == "undefined" || 
doesDefinePropertyWork(document.createElement("div")); 
if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { 
var definePropertyFallback = Object.defineProperty; 
} 
} 
if (!Object.defineProperty || definePropertyFallback) { 
var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; 
var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " 
var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + 
"on this javascript engine"; 
Object.defineProperty = function defineProperty(object, property, descriptor) { 
if ((typeof object != "object" && typeof object != "function") || object === null) { 
throw new TypeError(ERR_NON_OBJECT_TARGET + object); 
} 
if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) { 
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); 
} 
// make a valiant attempt to use the real defineProperty 
// for I8's DOM elements. 
if (definePropertyFallback) { 
try { 
return definePropertyFallback.call(Object, object, property, descriptor); 
} catch (exception) { 
// try the shim if the real one doesn't work 
} 
} 
// If it's a data property. 
if (owns(descriptor, "value")) { 
// fail silently if "writable", "enumerable", or "configurable" 
// are requested but not supported 
/* 
// alternate approach: 
if ( // can't implement these features; allow false but not true 
!(owns(descriptor, "writable") ? descriptor.writable : true) || 
!(owns(descriptor, "enumerable") ? descriptor.enumerable : true) || 
!(owns(descriptor, "configurable") ? descriptor.configurable : true) 
) 
throw new RangeError( 
"This implementation of Object.defineProperty does not " + 
"support configurable, enumerable, or writable." 
); 
*/ 
if (supportsAccessors && (lookupGetter(object, property) || 
lookupSetter(object, property))) 
{ 
// As accessors are supported only on engines implementing 
// `__proto__` we can safely override `__proto__` while defining 
// a property to make sure that we don't hit an inherited 
// accessor. 
var prototype = object.__proto__; 
object.__proto__ = prototypeOfObject; 
// Deleting a property anyway since getter / setter may be 
// defined on object itself. 
delete object[property]; 
object[property] = descriptor.value; 
// Setting original `__proto__` back now. 
object.__proto__ = prototype; 
} else { 
object[property] = descriptor.value; 
} 
} else { 
if (!supportsAccessors) { 
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); 
} 
// If we got that far then getters and setters can be defined !! 
if (owns(descriptor, "get")) { 
defineGetter(object, property, descriptor.get); 
} 
if (owns(descriptor, "set")) { 
defineSetter(object, property, descriptor.set); 
} 
} 
return object; 
}; 
} 
// ES5 15.2.3.7 
// http://es5.github.com/#x15.2.3.7 
if (!Object.defineProperties) { 
Object.defineProperties = function defineProperties(object, properties) { 
for (var property in properties) { 
if (owns(properties, property) && property != "__proto__") { 
Object.defineProperty(object, property, properties[property]); 
} 
} 
return object; 
}; 
}

EcmaScript6的类继承。
class module extends Base { 
constructor() { 
} 
}

越玩越像java了,不过es6很多浏览器还不支持。
最后推荐的写法:
if (!Object.create) { 
Object.create = function create(o) { 
var F = function(){}; 
F.prototype = o; 
var result = new F(); 
F.prototype = null; 
return result; 
} 
}
Javascript 相关文章推荐
javascript 实现父窗口引用弹出窗口的值的脚本
Aug 07 Javascript
javascript 不间断的图片滚动并可点击
Jan 15 Javascript
js修改table中Td的值(定义td的单击事件)
Jan 10 Javascript
IE、FF浏览器下修改标签透明度
Jan 28 Javascript
深入理解JavaScript系列(36):设计模式之中介者模式详解
Mar 04 Javascript
javascript中利用柯里化函数实现bind方法
Apr 29 Javascript
jquery自定义插件结合baiduTemplate.js实现异步刷新(附源码)
Dec 22 Javascript
js禁止表单重复提交
Aug 29 Javascript
JS实现匀速与减速缓慢运动的动画效果封装示例
Aug 27 Javascript
基于vue实现移动端圆形旋钮插件效果
Nov 28 Javascript
如何用JS实现网页瀑布流布局
Apr 24 Javascript
js判断两个数组相等的5种方法
May 06 Javascript
基于jquery的多功能软键盘插件
Jul 25 #Javascript
基于jQuery判断两个元素是否有重叠部分的代码
Jul 25 #Javascript
JavaScript中的apply()方法和call()方法使用介绍
Jul 25 #Javascript
关于JavaScript中原型继承中的一点思考
Jul 25 #Javascript
原生js 秒表实现代码
Jul 24 #Javascript
javascript设计模式 接口介绍
Jul 24 #Javascript
javascript设计模式 封装和信息隐藏(上)
Jul 24 #Javascript
You might like
PHP的分页功能
2007/03/21 PHP
人尽可用的Windows技巧小贴士之下篇
2007/03/22 PHP
PHP把MSSQL数据导入到MYSQL的方法
2014/12/27 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
2019/10/02 PHP
jquery.alert 弹出式复选框实现代码
2009/06/15 Javascript
让iframe子窗体取父窗体地址栏参数(querystring)
2009/10/13 Javascript
用原生JavaScript实现jQuery的$.getJSON的解决方法
2013/05/03 Javascript
用jquery修复在iframe下的页面锚点失效问题
2014/08/22 Javascript
js中confirm实现执行操作前弹出确认框的方法
2014/11/01 Javascript
jquery实现超简洁的TAB选项卡效果代码
2015/08/28 Javascript
实例讲解jquery中mouseleave和mouseout的区别
2016/02/17 Javascript
基于AngularJS实现iOS8自带的计算器
2016/09/12 Javascript
JavaScript定义函数_动力节点Java学院整理
2017/06/27 Javascript
Node.js 8 中的重要新特性
2017/06/28 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
2017/07/21 Javascript
Vue.js实现列表清单的操作方法
2017/11/15 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
用webpack4开发小程序的实现方法
2019/06/04 Javascript
layui输入框只允许输入中文且判断长度的例子
2019/09/18 Javascript
解决layer.confirm快速点击会重复触发事件的问题
2019/09/23 Javascript
vue 实现 rem 布局或vw 布局的方法
2019/11/13 Javascript
详解JavaScript中分解数字的三种方法
2021/01/05 Javascript
[04:20]DOTA2-DPC中国联赛 正赛 VG vs LBZS 选手采访 1月19日
2021/03/11 DOTA
Python中的groupby分组功能的实例代码
2018/07/11 Python
Django实现web端tailf日志文件功能及实例详解
2019/07/28 Python
python中时间转换datetime和pd.to_datetime详析
2019/08/11 Python
Python 实现将numpy中的nan和inf,nan替换成对应的均值
2020/06/08 Python
python主要用于哪些方向
2020/07/05 Python
Python LMDB库的使用示例
2021/02/14 Python
python中最小二乘法详细讲解
2021/02/19 Python
挪威户外活动服装和装备购物网站:Bergfreunde挪威
2016/10/20 全球购物
Fnac西班牙官网:法国文化和电子产品零售商
2021/03/14 全球购物
部门活动策划方案
2014/08/16 职场文书
员工自我工作评价
2015/03/06 职场文书
详解Laravel服务容器的优势
2021/05/29 PHP
mysql 8.0.27 绿色解压版安装教程及配置方法
2022/04/20 MySQL