JS 继承与扩展

来源:互联网 发布:数据库并发保证一致性 编辑:程序博客网 时间:2024/05/21 06:02

先给大家介绍下JavaScript实现继承的几种方式,然后再详细讨论讨论JS的prototype和constructor。

一 JavaScript实现继承的方式

1. 继承第一种方式:对象冒充 

  先定义一个父类:

function parent(name){ 
    this.name = name
    this.hello = function(){ 
      alert(this.name); 
    } 
  }

再定义一个子类:

通过以下3行实现将parent的属性和方法追加到Child中,从而实现继承
第一步:this.method是作为一个临时的属性,并且指向Parent所指向的对象,
第二步:执行this.method方法,即执行parent所指向的对象函数 。这就相当与在对象自己身上调用parent的hello函数,parent的this指向了child。相当与 parent.call(this);
第三步:销毁this.method属性,即此时Child就已经拥有了Parent的所有属性和方法 。

注意:this.method已经执行,删不删都一样,不影响属性的添加,区别只在构造出的对象中是否存在该方法,如果不删除,还可以在实例中调用该方法,修改那两个成员的值

function child(name, pwd){
  this.method = Parent;
  this.method(name);
  delete this.method;
  this.pwd = pwd; 
  this.world = function(){
  alert(this.pwd);
  };
  }

测试:

var parent = new parent("zhangsan");
var child = new child("lisi","123456");
parent.hello();
child.hello();
child.world();

parent和child的hello方法是相互独立的,修改任何一方都不会影响另外一个。

2. 继承第二种方式:call()方法方式 

call方法是Function类中的方法
call方法的第一个参数的值赋值给类(即方法)中出现的this
call方法的第二个参数开始依次赋值给类(即方法)所接受的参数

function test(str){
     alert(this.name + " " + str);
}
var object = new Object();
object.name = "zhangsan";
test.call(object,"langsin");//此时,第一个参数值object传递给了test类(即方法)中出现的this,而第二个参数"langsin"则赋值给了test类(即方法)的str 

先定义一个父类:

function parent(name){ 
    this.name = name
    this.hello = function(){ 
      alert(this.name); 
    } 
  }

再定义一个子类:

function child(name, pwd){

parent.call(this, name);

this.pwd = pwd;
this.world = function(){
alert(this.pwd);
}

}

parent和child的hello方法是相互独立的,修改任何一方都不会影响另外一个。

var parent = new parent("zhangsan");
var child = new child("lisi","123456");
parent.hello();
child.hello();
child.world();

3. 继承的第三种方式:apply()方法方式 

apply方法和call 方法类似

 apply方法接受2个参数, 
    A、第一个参数与call方法的第一个参数一样,即赋值给类(即方法)中出现的this 
    B、第二个参数为数组类型,这个数组中的每个元素依次赋值给类(即方法)所接受的参数

function parent(name){
this.name = name;
this.hello = function(){
alert(this.name);
}
}
function child(name,password){
parent.apply(this,new Array(name));
this.pwd = pwd;
this.world = function(){
alert(this.pwd);
}
}
var parent = new parent("zhangsan");
var child = new child("lisi","123456");
parent.hello();
child.hello();
child.world();

4. 继承的第四种方式:原型链方式

即子类通过prototype将所有在父类中通过prototype追加的属性和方法都追加到child,从而实现了继承 

function parent(){
}
parent.prototype.hello = "hello";
parent.prototype.sayHello = function(){
alert(this.hello);
}

function child(){
}
child.prototype = new parent();//这行的作用是:将parent中将所有通过prototype追加的属性和方法都追加到child,从而实现了继承 

child.prototype.constructor = child; //纠正child的prototype的constructor
child.prototype.world = "world";
child.prototype.sayWorld = function(){
alert(this.world);
}

var c = new Child();
c.sayHello();
c.sayWorld();

child.prototype = new parent();它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。

任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有"child.prototype = new parent();"这一行,child.prototype.constructor是指向child的;加了这一行以后,child.prototype.constructor指向parent。

alert(child.prototype.constructor == parent); //true

更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。

alert(c.constructor == child.prototype.constructor); // true 

因此,在运行"child.prototype = new parent();"这一行之后,c.constructor也指向parent!

这显然会导致继承链的紊乱(c明明是用构造函数child生成的),因此我们必须手动纠正,将child.prototype对象的constructor值改为child。child.prototype.constructor = child;就是做这样的事情的。

5. 继承的第五种方式:混合方式

混合了call方式、原型链方式

function Parent(hello){
this.hello = hello;
}
Parent.prototype.sayHello = function(){
alert(this.hello);
}

function Child(hello,world){
Parent.call(this,hello);//将父类的属性继承过来
this.world = world;//新增一些属性
}

Child.prototype = new Parent();//将父类的方法继承过来 

Child.prototype.constructor = Child;

Child.prototype.sayWorld = function(){//新增一些方法 

alert(this.world);
}

var c = new Child("zhangsan","lisi");
c.sayHello();
c.sayWorld();

二 JS的prototype和constructor

prototype原型prototype方式的属性查询可以理解为js独有的一个机制

 

就是说,js读取一个对象属性的时候,对象本身若找不到,则会去读取构造函数的prototype对象的同名属性,然后若还是找不到,则去读取Object构造函数的prototype对象的同名属性——即所谓的“继承”... 

如果要实现继承关系A->B,则想要A继承B的属性,则需要自己去维护这个prototype对象。

 

constructor:它是每个对象都有的一个属性,它引用初始化这个对象时候的构造函数。js这也是独有的一个机制。它有默认值。

你可以不去维护它,这个时候你不去用它,也不会有任何问题。但是,当你想让它正确工作的时候,则就需要我们去维护它了!



0 0
原创粉丝点击