JavaScript继承的一些工具函数
在阅读精通JavaScript(图灵计算机科学丛书)里面有讲解javascript继承的一些东东。
其一是讲解DouglasCrockford的js
代码如下:
//简单的辅助函数,让你可以将新函数绑定到对象prototype上 Function.prototype.method = function (name, func) { this .prototype[name] = func; return this ; } //一个相当复杂的函数,允许你方便地从其他对象继承函数, //同时仍然可以调用属于父对象的那些方法 Function.method( 'inherits' , function (parent) { var d = {}; //记录我们目前所在父层次的级数 var p = ( this .prototype = new parent()); //继承父对象的方法 //创建一个新的名位uber的特权函数 //调用它时会执行所有在继承时被重写的函数 this .method( "uber" , function uber(name) { if (!(name in d)) { d[name] = 0; //继承级数默认为0 } var f, /*要执行的函数*/ r, /*函数返回值*/ t = d[name], v = parent.prototype; /*父对象的prototype*/ if (t) { //如果我们已经在某个uber函数内 上溯到必要的级数已找到原始的prototype while (t) { v = v.constructor.prototype; t -= 1; } f = v[name]; //从prototype中获得函数 } else { //uber第一次调用 从prototype获得要执行的函数 f = p[name]; if (f == this [name]) { //如果函数属于当前prototype 则改为调用父对象的prototype f = v[name]; } } d[name] += 1; //记录我们在继承堆栈中所在位置 //使用除第一个以外所有的arguments 调用函数 第一个参数是执行的匿名函数名 r = f.apply( this , Array.prototype.slice.apply(arguments, [1])); d[name] -= 1; //恢复继承堆栈 return r; }); return this ; }); //只继承父对象特定的函数。而非使用new parent()的继承的所有函数 Function.method( "swiss" , function (parent) { for ( var i = 1; i < arguments.length; i++) { var name = arguments[i]; this .prototype[name] = parent[name]; } return this ; }); /* Function.prototype.method 它提供了一个简单的方法,把函数于构造函数原型关联起来。 之所以有效,是因为所有的构造函数本身都是函数,所以能获得method这个新方法 Function.prototype.inherits这一函数可以用于提供简单的对象继承,它的代码主要围绕任意对象方法中调用 this.uber(methodname)为中心,并在让这个uber方法执行它要覆盖的父对象的方法。 Function.prototype.swiss这是.method函数的增强版,可以用于单一父对象获取多个函数。如果有多个父对象上 就能获得可用的多对象继承 */ |
调用代码:
function Person(name) { this .name = name; } Person.method( "getName" , function () { return this .name; }); function User(name, password) { this .name = name; this .password = password; } User.inherits(Person); User.method( "getPassword" , function () { return this .password; }); User.method( "getName" , function () { return "My name is :" + this .uber( "getName" ); }); var p = new Person( "123" ); alert(p.getName()); var u = new User( "abc" , "456" ); alert(u.getPassword()); alert(u.getName()); |
第二个工具函数是base库
/* Base.js, version 1.1a Copyright 2006-2010, Dean Edwards License: http://www.opensource.org/licenses/mit-license.php */ var Base = function () { // dummy }; Base.extend = function (_instance, _static) { // subclass var extend = Base.prototype.extend; // build the prototype Base._prototyping = true ; var proto = new this ; extend.call(proto, _instance); proto.base = function () { // call this method from any other method to invoke that method's ancestor }; delete Base._prototyping; // create the wrapper for the constructor function //var constructor = proto.constructor.valueOf(); //-dean var constructor = proto.constructor; var klass = proto.constructor = function () { if (!Base._prototyping) { if ( this ._constructing || this .constructor == klass) { // instantiation this ._constructing = true ; constructor.apply( this , arguments); delete this ._constructing; } else if (arguments[0] != null ) { // casting return (arguments[0].extend || extend).call(arguments[0], proto); } } }; // build the class interface klass.ancestor = this ; klass.extend = this .extend; klass.forEach = this .forEach; klass.implement = this .implement; klass.prototype = proto; klass.toString = this .toString; klass.valueOf = function (type) { //return (type == "object") ? klass : constructor; //-dean return (type == "object" ) ? klass : constructor.valueOf(); }; extend.call(klass, _static); // class initialisation if ( typeof klass.init == "function" ) klass.init(); return klass; }; Base.prototype = { extend: function (source, value) { if (arguments.length > 1) { // extending with a name/value pair var ancestor = this [source]; if (ancestor && ( typeof value == "function" ) && // overriding a method? // the valueOf() comparison is to avoid circular references (!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) && /\bbase\b/.test(value)) { // get the underlying method var method = value.valueOf(); // override value = function () { var previous = this .base || Base.prototype.base; this .base = ancestor; var returnValue = method.apply( this , arguments); this .base = previous; return returnValue; }; // point to the underlying method value.valueOf = function (type) { return (type == "object" ) ? value : method; }; value.toString = Base.toString; } this [source] = value; } else if (source) { // extending with an object literal var extend = Base.prototype.extend; // if this object has a customised extend method then use it if (!Base._prototyping && typeof this != "function" ) { extend = this .extend || extend; } var proto = {toSource: null }; // do the "toString" and other methods manually var hidden = [ "constructor" , "toString" , "valueOf" ]; // if we are prototyping then include the constructor var i = Base._prototyping ? 0 : 1; while (key = hidden[i++]) { if (source[key] != proto[key]) { extend.call( this , key, source[key]); } } // copy each of the source object's properties to this object for ( var key in source) { if (!proto[key]) extend.call( this , key, source[key]); } } return this ; } }; // initialise Base = Base.extend({ constructor: function () { this .extend(arguments[0]); } }, { ancestor: Object, version: "1.1" , forEach: function (object, block, context) { for ( var key in object) { if ( this .prototype[key] === undefined) { block.call(context, object[key], key, object); } } }, implement: function () { for ( var i = 0; i < arguments.length; i++) { if ( typeof arguments[i] == "function" ) { // if it's a function, call it arguments[i]( this .prototype); } else { // add the interface using the extend method this .prototype.extend(arguments[i]); } } return this ; }, toString: function () { return String( this .valueOf()); } }); |
调用代码:
var Person = Base.extend({ constructor: function (name) { this .name = name; }, getName: function () { return this .name; } }); var User = Person.extend({ constructor: function (name, password) { this .base(name); this .password = password; }, getPassWord: function () { return this .password; } }); var p = new Person( "123" ); alert(p.getName()); var u = new User( "456" , "abc" ); alert(u.getName()); alert(u.getPassWord()); |
有关base的详细介绍:http://dean.edwards.name/weblog/2006/03/base/
windows技术爱好者
标签:
javascript
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构