在Java中对象是由类实例化的,在类中已经设置好了属性和方法,实例化后的对象也就有了这些属性和方法,是先有的属性和方法,后有的对象及属性的值;
而在JavaScript中呢?我不太懂了,找不到对应Java中类的概念,属性和值好像是一起产生的,比如这个,求指点:
var obj = {a:1,b:2,x:function(){return this.a+this.b;}};
如果我想再创建一个属性方法一样,但是值不一样的对象,怎么做才能代码复用呢?你看这样对吗:
function MyClass(a,b,c=999){
this.a=a;
this.b=b;
this.c=c;
}
MyClass.prototype={
x:function(){return this.a+this.b;}
}
var obj1 = new MyClass(1,2);
var obj2 = new MyClass(3,4);
如果我想复用上面代码,在基础上增加一些属性和方法,也就是说要实现Java中的“继承”,我应该怎么做呢,你看这样对吗:
function MyClass(a,b,c=999){
this.a=a;
this.b=b;
this.c=c;
}
MyClass.prototype.x=function(){return this.a+this.b;};
function MySubClass(a,b,d){
MyClass.apply(this,[a,b]);
this.d=d;
}
for(everything in MyClass.prototype){
MySubClass.prototype[everything] = MyClass.prototype[everything];
}
MySubClass.prototype.y=function(){return this.c;}
var obj1 = new MyClass(1,2);
var obj3 = new MySubClass(5,6,7);
为了继承父类的属性,我使用了apply方法,为了继承父类的方法,我把父类的prototype对象复制到子类的prototype,然后再修改。。。这样做之后,我的子类确实继承并扩展了父类的属性。不过我发现,我这个写法有问题:
从控制台查看obj3,属性a、b以及方法x是这个对象固有属性,看不出来是继承自父类的,这和我理解的Java中的继承是不一样的,我理解的继承是obj3没有a这个属性,访问obj3.a应该从MyClass.prototype中找,所以我以上写的应该是错的。。。
于是我把前面推翻,换了一个写法:
function MyClass(a,b){
this.a=a;
this.b=b;
}
MyClass.prototype={
a:0,
b:0,
c:999,
x:function(){return this.a+this.b;}
};
function MySubClass(a){
this.a=a;
}
function Temp(){}
Temp.prototype=MyClass.prototype;
MySubClass.prototype=new Temp();
MySubClass.prototype.d=0;
MySubClass.prototype.y=function(){return this.c;}
MySubClass.prototype.a=888;
var obj1 = new MyClass(1,2);
var obj3 = new MySubClass(3);
console.info(obj1);
console.info(obj3);
console.info(MyClass.prototype);
console.info(MySubClass.prototype);
子类的prototype我不从父类复制过来,改成继承过来,但是我查看控制台,发现和前一本版一样,父类的属性仍然在子类直接找到了,同时还出现了别的问题,构造函数变成Object了:
我现在更困惑了,我写的最后两个版本哪个更对呢
—————————————————————————————————————————
好像在控制台中查看对象,看不出来这个对象的属性是直属属性还是继承来的属性,也找不到这个对象的父类的信息,__proto__指的是构造这个对象的原型对象,__proto__是原型链,不是Java中的继承链,和子类父类间的继承没有关系,我这样理解对吗
—————————————————————————————————————————
还有一个问题:
console.info(obj3.__proto__);//MySubClass {x=function(),y=function()}
console.info(obj3.__proto__.constructor);//MySubClass(a,b,d)
console.info(MySubClass.prototype);////MySubClass {x=function(),y=function()}
console.info(MySubClass.prototype.constructor);//MySubClass(a,b,d)
console.info(MySubClass.prototype.constructor===MySubClass);//true
对象obj3.__proto__指的是创建这个对象的原型对象,也就是MySubClass.prototype,这没问题,我能理解;那这个原型对象是怎么来的呢?好像是天生就有,而且这个原型对象的contructor指的是构造函数MySubClass(叫构造函数对不对?),这是为什么呢,语法规定的?万一是个匿名构造函数呢,它指向什么?
提到匿名函数,我又测试了一段代码:
var noName1=function(a,b){
this.a=a;
this.b=b;
}
var noName2=new Function("a","b","this.a=a;this.b=b");
console.info(noName1)//function()
console.info(noName1.prototype)//Object{ }
console.info(noName1.prototype.constructor)//function()
console.info(noName2)//anonymous(a,b)
console.info(noName2.prototype)//anonymous{ }
console.info(noName2.prototype.constructor)//anonymous(a,b)
console.info(noName1.constructor===noName2.constructor)//true Function()
从这段代码可以看出来,函数也是对象,noName1和noName2首先是函数,同时也是对象,都是由构造函数Function产生,但又有点区别,原型不同,一个是Object空对象,另一个是anonymous,我的理解对吗
JS
是基于对象而不是面向对象的,它的继承是伪继承。你的代码是对的,虽然并不全面,但是初步能用了,而且体现出了
JS
中继承技巧的精髓,看来你对JS
还是有相当了解的。PS:
JS
中函数参数是没有默认值的。补充回答:
JS
中可以通过原型链继承来做到你想实现的效果: