浅谈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 相关文章推荐
jQuery 改变CSS样式基础代码
Feb 11 Javascript
jQuery 创建Dom元素
May 07 Javascript
用Javascript实现Windows任务管理器的代码
Mar 27 Javascript
关于extjs treepanel复选框选中父节点与子节点的问题
Apr 02 Javascript
分类解析jQuery选择器
Nov 23 Javascript
jQuery编写设置和获取颜色的插件
Jan 09 Javascript
十大热门的JavaScript框架和库
Mar 21 Javascript
webpack2.0配置postcss-loader的方法
Aug 17 Javascript
Angular4学习之Angular CLI的安装与使用教程
Jan 04 Javascript
在Vue项目中引入腾讯验证码服务的教程
Apr 03 Javascript
jQuery表单校验插件validator使用方法详解
Feb 18 jQuery
Node在Controller层进行数据校验的过程详解
Aug 28 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函数eval()介绍和使用示例
2014/08/20 PHP
php自动更新版权信息显示的方法
2015/06/19 PHP
用PHP代码给图片加水印
2015/07/01 PHP
PHP中类的继承和用法实例分析
2016/05/24 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
符合W3C网页标准的iframe标签的使用方法
2007/07/19 Javascript
jQuery 使用手册(四)
2009/09/23 Javascript
文本框回车提交与禁止提交示例
2013/09/27 Javascript
分享几种比较简单实用的JavaScript tabel切换
2015/12/31 Javascript
javascript中的 object 和 function小结
2016/08/14 Javascript
JS限定手机版中图片大小随分辨率自动调整的方法
2016/12/05 Javascript
详解vuelidate 对于vueJs2.0的验证解决方案
2017/03/09 Javascript
JS回调函数基本定义与用法实例分析
2017/05/24 Javascript
vue2.0 中#$emit,$on的使用详解
2017/06/07 Javascript
Vue.js结合Ueditor富文本编辑器的实例代码
2017/07/11 Javascript
jquery 键盘事件的使用方法详解
2017/09/13 jQuery
基于js 字符串indexof与search方法的区别(详解)
2017/12/04 Javascript
原生javascript实现类似vue的数据绑定功能示例【观察者模式】
2020/02/24 Javascript
从零学python系列之浅谈pickle模块封装和拆封数据对象的方法
2014/05/23 Python
python通过pil模块获得图片exif信息的方法
2015/03/16 Python
python 专题九 Mysql数据库编程基础知识
2017/03/16 Python
python和shell监控linux服务器的详细代码
2018/06/22 Python
如何在Django中添加没有微秒的 DateTimeField 属性详解
2019/01/30 Python
python3实现zabbix告警推送钉钉的示例
2019/02/20 Python
pyqt5 QProgressBar清空进度条的实例
2019/06/21 Python
Django框架视图层URL映射与反向解析实例分析
2019/07/29 Python
Python如何使用函数做字典的值
2019/11/30 Python
python3.6环境下安装freetype库和基本使用方法(推荐)
2020/05/10 Python
Python 字典中的所有方法及用法
2020/06/10 Python
Python函数参数定义及传递方式解析
2020/06/10 Python
Python函数__new__及__init__作用及区别解析
2020/08/31 Python
CSS3的RGBA中关于整数和百分比值的转换
2015/08/04 HTML / CSS
欧克利英国官网:Oakley英国
2019/08/24 全球购物
美容院店长岗位职责
2014/04/08 职场文书
作文评语集锦
2014/12/25 职场文书
Eclipse+Java+Swing+Mysql实现电影购票系统(详细代码)
2022/01/18 Java/Android