继承是每一个javascript工具库和框架都不可少的部分。来看看各大类库的实现吧。
1, prototype.1.7.1.js
function extend(destination, source) { for (var property in source) destination[property] = source[property]; return destination; }
2, 鼎鼎大名的jQuery.2.0.3
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; };
代码多了这么多,多了深拷贝和函数方式
3, underscore
_.extend = function(obj) { each(slice.call(arguments, 1), function(source) { if (source) { for (var prop in source) { obj[prop] = source[prop]; } } }); return obj; };
4,庞大的angular
function extend(dst) { var h = dst.$$hashKey; forEach(arguments, function(obj) { if (obj !== dst) { forEach(obj, function(value, key) { dst[key] = value; }); } }); setHashKey(dst,h); return dst; }
5, 第一个项目中使用的ligerUI
Function.prototype.ligerExtend = function (parent, overrides) { if (typeof parent != 'function') return this; //保存对父类的引用 this.base = parent.prototype; this.base.constructor = parent; //继承 var f = function () { }; f.prototype = parent.prototype; this.prototype = new f(); this.prototype.constructor = this; //附加属性方法 if (overrides) $.extend(this.prototype, overrides); };
6, dojo
extend: function(ctor, props){ // summary: // Adds all properties and methods of props to constructor's // prototype, making them available to all instances created with // constructor. // ctor: Object // Target constructor to extend. // props: Object // One or more objects to mix into ctor.prototype for(var i=1, l=arguments.length; i<l; i++){ lang._mixin(ctor.prototype, arguments[i]); } return ctor; // Object },
_mixin: function(dest, source, copyFunc){ // summary: // Copies/adds all properties of source to dest; returns dest. // dest: Object // The object to which to copy/add all properties contained in source. // source: Object // The object from which to draw all properties to copy into dest. // copyFunc: Function? // The process used to copy/add a property in source; defaults to the Javascript assignment operator. // returns: // dest, as modified // description: // All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions // found in Object.prototype, are copied/added to dest. Copying/adding each particular property is // delegated to copyFunc (if any); copyFunc defaults to the Javascript assignment operator if not provided. // Notice that by default, _mixin executes a so-called "shallow copy" and aggregate types are copied/added by reference. var name, s, i, empty = {}; for(name in source){ // the (!(name in empty) || empty[name] !== s) condition avoids copying properties in "source" // inherited from Object.prototype. For example, if dest has a custom toString() method, // don't overwrite it with the toString() method that source inherited from Object.prototype s = source[name]; if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){ dest[name] = copyFunc ? copyFunc(s) : s; } } if(has("bug-for-in-skips-shadowed")){ if(source){ for(i = 0; i < _extraLen; ++i){ name = _extraNames[i]; s = source[name]; if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){ dest[name] = copyFunc ? copyFunc(s) : s; } } } } return dest; // Object },
除了5之外,基本上用到的是拷贝式继承。简单,通用(对数组,对象的继承也很好用,喜欢)
6是原型继承
当然了,还有一些其他方式,不过实际用的不多
比如:
对象冒充继承
function Parent(firstname) { this.fname=firstname; this.age=40; this.sayAge=function() { console.log(this.age); } } function Child(firstname) { this.parent=Parent; this.parent(firstname); delete this.parent; this.saySomeThing=function() { console.log(this.fname); this.sayAge(); } } var mychild=new Child("李"); mychild.saySomeThing();
采用call方法改变函数上下文实现继承
function Parent(firstname) { this.fname=firstname; this.age=40; this.sayAge=function() { console.log(this.age); } } function Child(firstname) { this.saySomeThing=function() { console.log(this.fname); this.sayAge(); } this.getName=function() { return firstname; } } var child=new Child("张"); Parent.call(child,child.getName()); child.saySomeThing();
以上就是查找各大类库继承方式和在网络上一些继承的方法。
推荐:拷贝式继承,虽然性能差点。