原型与原型链
|
---|
封装(点击打开链接)构造函数的继承(点击打开链接)非构造函数的继承(点击打开链接)
|
Javascript规定,每一个构造函数都有一个prototype 属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
| 这意味着,我们可以把那些不变的属性和方法,直接定义在prototype 对象上。
| function Cat(name,color){ this.name = name; this.color = color; } Cat.prototype.type = "猫科动物"; Cat.prototype.eat = function(){alert("吃老鼠")}; | 然后,生成实例。 | var cat1 = new Cat("大毛","黄色"); var cat2 = new Cat("二毛","黑色"); alert(cat1.type); // 猫科动物 cat1.eat(); // 吃老鼠 | 这时所有实例的type 属性和eat() 方法,其实都是同一个内存地址,指向prototype 对象,因此就提高了运行效率。 | alert(cat1.eat == cat2.eat); //true |
Prototype模式的验证方法 |
---|
为了配合prototype 属性,Javascript定义了一些辅助方法,帮助我们使用它。, | isPrototypeOf() | 这个方法用来判断,某个proptotype 对象和某个实例之间的关系。 | alert(Cat.prototype.isPrototypeOf(cat1)); //truealert(Cat.prototype.isPrototypeOf(cat2)); //true | hasOwnProperty() | 每个实例对象都有一个hasOwnProperty() 方法,用来判断某一个属性到底是本地属性,还是继承自prototype 对象的属性。 | alert(cat1.hasOwnProperty("name")); // truealert(cat1.hasOwnProperty("type")); // false | in运算符 | in 运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。 | alert("name" in cat1); // truealert("type" in cat1); // true | in 运算符还可以用来遍历某个对象的所有属性。 | for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); } |
继承 |
---|
function Animal(){ this.species = "动物";}function Cat(name,color){ this.name = name; this.color = color;} |
---|
构造函数绑定 | 使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行: | function Cat(name,color){Animal.apply(this, arguments);//Animal.call(this);(两种写法都可以输出) this.name = name; this.color = color; } var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物 | prototype模式 | 第二种方法更常见,使用prototype属性。 |
function Action() {} Action.prototype.Cando=function(){ console.log("saddd"); } function ben(){} ben.prototype=new Action(); var aas=new ben(); console.log(aas); 浅拷贝var Chinese = { nation:'中国' }; var Doctor ={ career:'医生'
} 这两个对象都是普通对象,不是构造函数,无法使用构造函数方法实现"继承"。
| |
|
---|
除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。 function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } c.uber = p; return c; }
|
var Doctor = extendCopy(Chinese); Doctor.career = '医生'; alert(Doctor.nation); // 中国 | 这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。 | 现在给Chinese添加一个"出生地"属性,它的值是一个数组 Chinese.birthPlaces = ['北京','上海','香港'];
通过extendCopy()函数,Doctor继承了Chinese。
var Doctor = extendCopy(Chinese);
我们为Doctor的"出生地"添加一个城市:
Doctor.birthPlaces.push('厦门');
Chinese的"出生地"也被改掉了!
alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门extendCopy()只是拷贝基本类型的数据,我们把这种拷贝叫做"浅拷贝"。这是早期jQuery实现继承的方式。
|
深拷贝 |
---|
就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。 | function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; }
var Doctor = deepCopy(Chinese); Chinese.birthPlaces = ['北京','上海','香港'];
Doctor.birthPlaces.push('厦门');
jQuery库使用的就是这种继承方法。
alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门 alert(Chinese.birthPlaces); //北京, 上海, 香港
|
|
|
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理