属性的继承:调用父类的构造函数call
1 2 3 4 5 6 7 8 9 10 11
| function Person(name, sex){ this.name = name; this.sex = sex; }
function Star(name, sex, age){ Person(name, sex); this.age = age; } var s = new Star("小名", "男", 20); console.log(s);
|
此时我们发现输出的s并没有name、sex属性,在Star类中是window对象调用的Person类,这是的name和sex属性都赋给了window对象。这里我们要修正this的指向。修改第7行代码如下:
1
| Person.call(this, name, sex);
|
方法的继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function Person(name, sex){ this.name = name; this.sex = sex; } Person.prototype.showName = function(){ console.log( this.name ); } var p = new Person("小红", "女");
function Star(name, sex, age){ Person.call(this, name, sex); this.age = age; }
Star.prototype = Person.prototype; var s = new Star("小名", "男", 20); console.log(s);
|
这时我们发现了一个问题,当你把一个原型对象赋给另一个原型对象时他们是按引用传递。这样的话,这两个对象的修改都会互相影响。
我们现在Star原型上添加一个方法,看看会不会影响到Person。
1
| Star.prototype.showJob = function(){}
|

我们发现在Person下也有showJob方法,这并不是我门希望得到的结果。
现在我们想到如果是一个基本类型的赋值就就不会出现这种问题,我们写个简单的继承方法,通过for in 遍历要继承对象的属性,然后一个一个赋值给父类对象。
1 2 3 4 5 6
| extend(Star.prototype, Person.prototype); function extend(son, father){ for(var attr in father){ son[attr] = father[attr]; } }
|
这样给Star添加方法就不会影响到Person对象。
这时悉心的同学有会发现问题:虽然属性可以复制,但是在Javascript中函数也是对象,函数赋给函数也存在引用关系?
现在来解释一下函数也是对象为什么就没有问题:虽然函数也是对象类型,但是它与对象类型还是有区别的。函数只能被重新赋值,不能被修改。
现在我们来讲解一下重新赋值与修改的区别。
1 2 3 4
| var a = [1,2,3]; var b = a; b.push(4); b = [1,2,3]
|
第3行修改了b,因为b是a的引用,所以a也被修改了。第4行给b重新赋值了,b由指向新的对象,对a并没有影响。
当然,上面的继承方法还是比较简单,现在我们来分析一下jquery的继承方法,有不正确的地方欢迎指正。
jquery-2.1.3.js extend源码。官方extend文档
jQuery.extend( [deep ], target, object1 [, objectN ] )
- deep:如果是true,就进行递归拷贝。
- target:继承的对象。
- object1、objectN :被继承的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;
if ( typeof target === "boolean" ) { deep = target;
target = arguments[ i ] || {}; i++; } if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { if ( (options = arguments[ i ]) != null ) { for ( name in options ) { src = target[ name ]; copy = options[ name ]; if ( target === copy ) { continue; } 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 : {}; } target[ name ] = jQuery.extend( deep, clone, copy ); } else if ( copy !== undefined ) { target[ name ] = copy; } } } } return target; };
|