在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,我的理解对吗
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
JavaScript 中没有真正的数据复制,所以相比“模拟类”的方式,用这种直接返回对象的方式也许是更自然的。
来看看结果:
这种模式写出来的
obj1与obj3中的x是直属属性,并非__proto__中的属性,也许好处就是避免了 @代码宇宙 所提到的__proto__的兼容性问题,然后 …… 也不用胡思乱想了 :)补充:
JavaScript 中还有一个
Object.create的东西:来看看结构:

详情可见《你不知道的 JavaScript》。
现代大部分面向对象语言基于类的面向对象程序设计语言。
由于历史原因,JS是原形继承(来自于古老的self语言,一种基于原型的面向对象程序设计语言)。
如果希望了解更多可以参考:
http://www.ruanyifeng.com/blog/2011/06/birth_of_javascript.html
http://segmentfault.com/a/1190000002596600
如果楼主希望在ES5中实现类似于基于类的继承可以参考:
http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html
又或者使用Babel、Typescript等于处理工具引入ECMAScript6的特性,将会有语言语法上获得类继承、参数默认值等一些新特性的支持。
参考:http://es6.ruanyifeng.com/#docs/class
JS是基于对象而不是面向对象的,它的继承是伪继承。你的代码是对的,虽然并不全面,但是初步能用了,而且体现出了
JS中继承技巧的精髓,看来你对JS还是有相当了解的。PS:
JS中函数参数是没有默认值的。补充回答:
JS中可以通过原型链继承来做到你想实现的效果: