javascript ES5 并没有所谓class 类,所以自然不能像c++,Java 那样子类继承父类,但是javascript还是可以实现继承的。
主要的继承方式分为构造函数继承和非构造函数继承
一、构造函数继承
构造一个原型函数,将需要定义的属性方法,通过指定 this 指向赋值;通过 new 方法实例化对象
1 function Person(name,sex,age,interest){ 2 this.name=name; 3 this.age=age; 4 this.sex=sex; 5 this.interest=interest; 6 }
为了在实例化对象后,每个对象相同的属性方法占用内存,我们将对象相同不变的方法和属性放在对象的prototype上,这样子每个实例相同部分都指向同一个内存地址
1 Person.prototype.action ="walk" ; 2 Person.prototype.mouth = "eat and speak"; 3 4 var Mary =new Person("mary","woman","20","shopping"); 5 var Tom = new Person("tom","man","23","play baseketball"); 6 7 "eat and speak" 8 Mary.action 9 //"walk" 10 Tom.mouth 11 //"eat and speak"
如果觉得要写很多prototype.什么很麻烦,也可以直接另外写一个"父类"方法函数,将不变的东西放在里面,然后"子类"的原型函数中进行函数绑定,例如在Person 中加 :
primaryPerson.apply(this, arguments); //primaryPerson 为"父类" 函数;
二、非构造函数方法
浅拷贝
1 var Person ={ 2 3 action :‘walk‘; 4 5 } 6 7 var Man ={ 8 name :"bentos", 9 age : "20", 10 bithPlace :shantou" 11 }
除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。
1 function extendCopy(p) { 2 var c = {}; 3 for (var i in p) { 4 c[i] = p[i]; 5 } 6 c.uber = p; 7 return c; 8 }
使用的时候,这样写
1 var Man= extendCopy(Person); 2 console.log(Person.action); 3 //walk
但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。
现在给Person添加一个"脸"属性,它的值是一个数组。
1 Person.face = [‘mouth‘,‘eye‘,‘nose‘];
通过extendCopy()函数,Man继承了Person。
1 var Man = extendCopy(Person);
然后,我们为Man的"face"添加一个属性:
1 Man.face.push(‘smalleye‘);
发生了什么,Person 的属性也被改变了
1 Person.face 2 ["mouth", "eye", "nose", "smalleye"]
所以,extendCopy()只是拷贝基本类型的数据,我们把这种拷贝叫做"浅拷贝"。这是早期jQuery实现继承的方式。
深拷贝
所谓"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。
1 function deepCopy(p, c) { 2 var c = c || {}; 3 for (var i in p) { 4 if (typeof p[i] === ‘object‘) { 5 c[i] = (p[i].constructor === Array) ? [] : {}; 6 deepCopy(p[i], c[i]); 7 } else { 8 c[i] = p[i]; 9 } 10 } 11 return c; 12 }
使用时这样写
var Person= deepCopy(Man);
现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性,这时,父对象不会受到影响了。