原型链
原型链是什么
构造函数或构造器具有prototype属性 对象具有__proto__属性 这就是之前学习的原型
如果构造函数或对象A A的原型指向构造函数或对象B B的原型在指向构造函数或对象C 以此类推 最终的构造函数或对象的原型指向Object的原型 由此形成一条链状结构 被称之为原型链
按照上述的描述 在B中定义的属性或方法 可以直接在A中使用并不需要定义 这就是继承 它允许每个对象来访问其原型链上的任何属性或方法。
原型链是ECMAScript标准中指定的默认实现继承方式。
// 原型链
function A(){
this.a = 'a';
}
// 通过构造函数创建对象
var a = new A();
function B(){
this.b = 'b';
}
// 将B的原型指向对象a
B.prototype = a;
// 通过构造函数创建对象
var b = new B();
console.log(b.b);// b
console.log(b.a);// a
function C(){
this.c = 'c';
}
// 将C的原型指向对象b
C.prototype = b;
// 通过构造函数创建对象
var c = new C();
console.log(c.c);// c
console.log(c.b);// b
console.log(c.a);// a
只继承于原型
处于对效率的考虑,尽量的将属性和方法添加到原型上。
1.不要为继承关系单独创建对象。
2.尽量减少运行时的方法搜索。
// 原型链
function A(){
// 将自有属性改写为原型属性
// this.a = 'a';
}
A.prototype.a = 'a';
function B(){
// this.b = 'b';
}
// 将B的原型指向
B.prototype = A.prototype;
B.prototype.b = 'b';
/*B.prototype = {
b : 'b'
}*/
function C(){
this.c = 'c';
}
// 将C的原型指向
C.prototype = B.prototype;
var c = new C();
console.log(c.c);// c
console.log(c.b);
console.log(c.a);// a
原型链的问题
原型链虽然很强大,用他可以实现JavaScript中的继承,但同时也存在着一些问题。
1.原型链实际上实在多个构造函数或对象之间共享属性和方法。
2.常见子类的对象时,不能向父级的构造函数传递任何参数。
在实际开发中很少会单独使用原型链。
// 原型链
function A(){
// 将自有属性改写为原型属性
// this.a = 'a';
}
A.prototype.a = 'a';
function B(){
// this.b = 'b';
}
// 将B的原型指向
B.prototype = A.prototype;
B.prototype.b = 'b';
function C(){
// this.c = 'c';
}
// 将C的原型指向
C.prototype = B.prototype;
C.prototype.c = 'c';
var c = new C();
console.log(c.c);// c
console.log(c.b);// b
console.log(c.a);// a
var a = new A();
console.log(a.a);
console.log(a.b);
console.log(a.c);
var b = new B();
console.log(b.a);
console.log(b.b);
console.log(b.c);
继承
原型式继承
所谓的原型式继承,就是定义一个函数,该函数中创建一个临时性 的构造函数,将作为参数传入的对象,作为这个构造函数的原型,左后返回这个构造函数的实例对象。
/*
定义一个函数 - 用于实现对象之间的继承
* 参数
* obj - 表示继承关系中的父级对象
* prop - 对象格式,表示继承关系中的子级对象的属性和方法
*/
function fn(obj, porp){
// 定义一个临时的构造函数
function Fun(){
// 遍历对象的属性和方法
for (var attrName in porp) {
// var attrValue = porp[attrName];
this[attrName] = porp[attrName];
}
}
// 将函数的参数作为构造函数的原型
Fun.prototype = obj;
// 将构造函数创建的对象进行返回
return new Fun();
}
var obj = {
name : '张无忌'
}
// 调用函数
var result = fn(obj, {
age : 18,
sayMe : function(){
console.log('this is function');
}
});
console.log(result.age);
result.sayMe();
注意;原型式继承具有与原型链相同的问题。
借助构造函数
无论是原型链还是原型式继承,都具有相同的问题。想要解决这样的问题的话,可以借助构造函数(也可以叫做伪造对象或经典继承)。
这种方式实现非常简单,就是在子对象的构造函数中调用父对象的构造函数,具体可以通过调用apply()和call()方法实现。
apply()和call()方法允许传递指定某个对形象的 this。对于继承来说,可以实现子对象构造函数中调用父对象的构造函数时,将子对象的this和父对象的this绑定在一起。
// 定义父级对象的构造函数
function Parent(){
this.parent = 'parent';
}
// 定义子级对象的构造函数
function Child(){
// 调用父级对象的构造函数 -> 使用apply()或call()方法
Parent.call(this);
this.child = 'child';
}
// 创建子级对象
var child = new Child();
console.log(child);
组合方式继承
组合继承,也佳作为经典继承,指的是将原型链或原型式继承和借助构造.函数的技术组合在一起,发挥二者长处的一种继承方式。
1.使用原型链或原型式继承实现对原型的属性和方法的继承。
2.通过借助构造函数实现对实例对象的属性和继承。
这样既通过在原型定义方法实现了函数的重用,又保证每个对象都有自己的专有属性。
function Parent(){
// 构造函数的自有属性
this.name = '张无忌';
}
// 构造函数的原型属性
Parent.prototype.age = 18;
function Child(){
// 继承父级构造函数中的自有属性
Parent.call(this);
this.job = '教主';
}
// 继承父级构造函数中的原型属性
Child.prototype = Parent.prototype;
var child = new Child();
console.log(child.job);
console.log(child.age);
console.log(child.name);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。