让我们接着上篇博客“java script-面向对象,你了解多少”继续java script的面向对象特征。这次说“继承”。
当开始听到java script的继承时有点疑惑,因为在java script中没有“类”的概念,怎么会继承呢?在java script中有什么呢?有对象,有函数,通常在一个对象中定义变量,属性,还定义函数(内置)。这种结构像极了类。继承其实就是复用一些东西,在java script中,我们可以把这种函数看成是一个类,然后进行继承。
“继承”在java script中可以实现继承的方法有两种形式。
一、原型继承法
每一个类(函数)都有一个原型,该原型上的成员在该类实例化时,会传给该类的实例化对象。实例化的对象上没有原型,但是它可以作为另一个类(函数)的原型,当以该对象为原型的类实例化时,该对象上的成员就会传给以它为原型的类的实例化对象上。这就是原型继承的本质。
function parentClass() {
// private field
var x = "I'm a parentClass field!";
// private method
function method1() {
alert(x);
alert("I'm a parentClass method!");
}
// public field
this.x = "I'm a parentClass object field!";
// public method
this.method1 = function() {
alert(x);
alert(this.x);
method1();
}
}
parentClass.prototype.method = function () {
alert("I'm a parentClass prototype method!");
}
parentClass.staticMethod = function () {
alert("I'm a parentClass static method!");
}
function subClass() {
// private field
var x = "I'm a subClass field!";
// private method
function method2() {
alert(x);
alert("I'm a subClass method!");
}
// public field
this.x = "I'm a subClass object field!";
// public method
this.method2 = function() {
alert(x);
alert(this.x);
method2();
}
this.method3 = function() {
method1();
}
}
// inherit
subClass.prototype = new parentClass();// new 新对象,赋值给子类.
// 等同于var p=parentClass();subClass.prototype=p;首先创建一个父类的实例化对象然后将该对象赋给子类的 prototype 属性.
subClass.prototype.constructor = subClass; // 将子类本身赋值给它的 prototype 的 constructor 属性。注意:这里赋值是没有 () 。
// test
var o = new subClass();// 实例化子类
alert(o instanceof parentClass); // true
alert(o instanceof subClass); // true
// 通过继承,父类中的所有公有实例成员都会被子类继承。子类的实例化对象既属于子类,也属于父类。
alert(o.constructor); // function subClass() {...} // 通过原型赋值,查看子类的实例化对象的 constructor 属性子类而不是其父类。
o.method1(); // I'm a parentClass field!
// I'm a subClass object field!
// I'm a parentClass field!
// I'm a parentClass method!
//子类继承来的公有实例方法中,如果调用了私有实例字段或者私有实例方法,则所调用的这些私有实例成员是属于父类的。
o.method2(); // I'm a subClass field!
// I'm a subClass object field!
// I'm a subClass field!
// I'm a subClass method!
//子类中定义的实例方法,如果调用了私有实例字段或者私有实例方法,则所调用的这些私有实例成员是属于子类的。
o.method(); // I'm a parentClass prototype method! 定义在父类原型上的方法,会被子类继承。
o.method3(); // Error!!!子类中定义的实例方法是不能访问父类中定义的私有实例成员的。
subClass.staticMethod(); // Error!!!静态成员是不会被继承的
二、调用继承法(对象冒充)
调用继承的本质是,在子类的构造器中,让父类的构造器方法在子类的执行上下文上执行,父类构造器方法上所有通过 this方式操作的内容实际上都都是操作的子类的实例化对象上的内容。因此,这种做法仅仅为了减少重复代码的编写。
function parentClass() {
// private field
var x = "I'm a parentClass field!";
// private method
function method1() {
alert(x);
alert("I'm a parentClass method!");
}
// public field
this.x = "I'm a parentClass object field!";
// public method
this.method1 = function() {
alert(x);
alert(this.x);
method1();
}
}
parentClass.prototype.method = function () {
alert("I'm a parentClass prototype method!");
}
parentClass.staticMethod = function () {
alert("I'm a parentClass static method!");
}
function subClass() {
// inherit
parentClass.call(this); //通过父类的 call方法,将子类的 this 指针传入。使父类方法在子类上下文中执行。这样,父类中的所有在父类内部通过 this方式定义的公有实例成员都会被子类继承。
// private field
var x = "I'm a subClass field!";
// private method
function method2() {
alert(x);
alert("I'm a subClass method!"