首页 > 代码库 > Javascript继承的最佳实践

Javascript继承的最佳实践

什么是继承?

继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。


在Javascript 中 没有 类的概念, 它是通过构造函数来产生 对象,

构造函数 就是一个普通的函数,通常当函数名 为 大写开头的,我们认为是构造函数,否则 就是普通的方法。

function A() {
    this.name = 'A Class instance';
}

function m1() {

}

既然 Javascript 是 通过构造函数来产生 对象,那我们怎么定义它的 属性、方法呢?

var a1 = new A();  是新创建一个A类对象,默认情况下,在构造函数中,使用this指向的是 新创建的对象;


而Javascript的对象属性 可以 晚绑定,即

var obj = {};
obj.name = 'obj1';
obj.say = function say() {
    console.log(this.name);
}
可以先产生对象,在需要增加属性时, 通过 obj.属性名  或 obj[‘属性名‘]  来添加属性。

所以我们在构造函数中 使用 this.属性名 来 定义产生的 对象 的 属性和方法。


function A() {    this.name = 'A Class instance';    this.say = function() {        console.log('Hi,I am ' + this.name);    }}var a1 = new A();var a2 = new A();a1.say(); // Hi,I am A Class instancea2.say(); // Hi,I am A Class instance

我们分析一下上面代码,

创建了 a1,a2 对象,在创建a1,a2 对象的时候 都为其添加一个say()方法,而这2个对象的 say方法 完全一样,

试想想 如果 创建n 个 A类对象,那是不是为这n个对象 添加一个say()方法,那是非常浪费内存。


所以在Javascript 中 引用了 prototype 原型的概念:

每一个构造函数都有一个prototype 对象,使用构造函数实例化一个对象,访问这个对象属性时,如果这个对象有该属性,则返回,否则就会在该对象的构造函数的prototype 上找,直到找到就返回,否则返回的是undefined


来验证一下:


 在上面代码中,A构造函数中没有定义say 方法,

但a1,a2 却 能够 调用say()方法,因为 A函数的prototype 默认指向的是 Object.prototype ;

此时内存中只保存Object.prototype.say,而A产生的对象 是通过原型机制,一层一层往上找,然后调用的。


所以通过 prototype原型机制,我们可以实现代码复用,和继承。

A.prototype.say = function() {
    console.log('Hi,I am ' + this.name);
}
function A() {
    this.name = 'A Class instance';
}
var a1 = new A();
var a2 = new A();
a1.say(); // Hi,I am A Class instance
a2.say(); // Hi,I am A Class instance

function B() {
    this.name = 'B Class instance';
}
B.prototype = new A();
B.prototype.constructor = B;

var b = new B();
b.say();

分析一下上面代码 执行结果:

我们定义了一个B类,并把他的prototype 指向 A的实例对象,

然后产生一个 b 对象,调用b对象 say() ,也输出了内容。

这是为什么呢?

访问 b 对象属性时, 如果不存在 ,就会在其 prototype 访问,

就是 访问a 对象的 prototype ,但a对象 prototype  默认 是 指向Object.prototype 的,

而我们在 Object.prototype 定义了say 方法,b 对象也能访问 say()方法, 就好像b 继承了 父类中的 属性一样。

这里我们也可以看出,一旦 原型链 过长,会导致 访问多个对象的prototype。

所以 在设计 的时候 应该 不超过 3层原型链,可以考虑其他方式。




Javascript 最佳的实践:

A.prototype.say = function() {
    console.log('Hi,I am ' + this.name);
}
function A() {
    this.name = 'A Class instance';
}
通过原型对象,添加方法,

通过构造函数 定义 对象的 属性。


继承还可以有很多种 实现方式, 比如 属性的复制等等,应当灵活运用。