JS中的原型与继承
原型:
Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。这个函数包括构造函数和普通函数,我们讲的更多是构造函数的原型,但是也不能否定普通函数也有原型。譬如普通函数:
function F(){
;
}
alert(F.prototype instanceof Object) //true
;
}
alert(F.prototype instanceof Object) //true
构造函数实例化对象的过程。
function A(x){
this.x=x;
}
var obj=new A(1);
实例化obj对象有三步:
- 1. 创建obj对象:var obj=new A(1);
- 2. 将obj的内部__proto__指向构造他的函数A的prototype. 类的实例对象的constructor属性永远指向"构造函数"的prototype.constructor. obj是没有prototype属性的,但是有内部的__proto__,通过__proto__来取得原型链上的原型属性和原型方法
- 3. 将obj作为this去调用构造函数A,从而设置成员(即对象属性和对象方法)并初始化。 (obj作为了this, 故 obj.x = x)
2种方式定义原型方法:
function A(x){
this.x=x;
this.say = function(){alert('hi')} ;
}
另一种:
A.prototype.say=function(){alert("Hi")};
区别:
前者的话,每一个对象都有关于say方法的一个副本。
后者,这个原型对象的say方法是唯一的副本给大家共享的。(这是通过内部的_proto_链来实现的。)
类继承
简单的继承实现。(js没有类,这里只是指构造函数)
function A(x){
this.x=x;
}
function B(x2,y){
this.tmpObj=A;
this.tmpObj(x2);
delete this.tmpObj;
this.y=y;
}
5、6、7行:(临时工角色)
创建临时属性tmpObj引用构造函数A,然后在B内部执行,执行完后删除。
B当然就拥有了x属性:
function A(x){
this.x=x;
}
function B(x2,y){
this.x=x2;
this.y=y;
}
当然B的x属性和A的x属性两者是独立,所以并不能算严格的继承。
第5、6、7行有更简单的实现:
A.call(this,x);
问题来了
B虽然继承了A构造对象的所有属性方法,但是不能继承A的原型对象的成员。
function A(x){
this.x=x;
}
A.prototype.a = "a";
function B(x2,y){
A.call(this, x);
this.y=y;
}
这样子B里面是没有继承 A.prototype.a = "a"; 属性的!
原型继承
解决上面的问题:
function A(x){
this.x = x;
}
A.prototype.a = "a";
function B(x2,y){
this.y = y;
A.call(this,x2);
}
B.prototype.b1 = function(){
alert("b1");
}
B.prototype = new A(); //注意A里面没有带参数!
// B先是被“类继承”一次,又被“原型继承”一次
//故B里面有两个x属性,一个为"a",一个undefined!
//这时,"原型属性x"要让位于"实例对象属性x",还是"a"了。
// 还要注意:此时,B.prototype.constructor就是构造对象A了!
//alert(B.prototype.constructor)出来后就是"function A(x){...}" 下面有解决的
//设置了原型方法b1,但是上面一行,原型指向改变,原来具有b1的原型对象被抛弃,自然又没有b1了
//再来个b2
B.prototype.b2 = function(){
alert("b2");
}
B.prototype.constructor = B;
// 将B原型的构造器重新指向了B构造函数
// 实例化B一个
var obj = new B(1,3);
类继承是这行:A.call(this.x);
原型继承是这行:B.prototype = new A();
如果没有
B.prototype.constructor = B;
那是不是obj = new B(1,3)会去调用A构造函数实例化呢?
答案是否定的:
你会发现obj.y=3,所以仍然是调用的B构造函数实例化的。
只是
obj.constructor===A //true
对于new B()的行为来说,执行了上面所说的通过构造函数创建实例对象的3个步骤:
- 第一步,创建空对象;
- 第二步,obj.__proto__ === B.prototype; (B.prototype是具有x,a,b2成员的。然后obj.constructor指向了B.prototype.constructor,即构造函数A;)
- 第三步,调用的构造函数B去设置和初始化成员,具有了属性x,y。
浙公网安备 33010602011771号