javascript面向对象 - JavaScript中关于“对象”、“继承”的困惑
巴扎黑
巴扎黑 2017-04-10 15:59:57
[JavaScript讨论组]

在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,我的理解对吗

巴扎黑
巴扎黑

全部回复(1)
黄舟

JS是基于对象而不是面向对象的,它的继承是伪继承。

你的代码是对的,虽然并不全面,但是初步能用了,而且体现出了JS中继承技巧的精髓,看来你对JS还是有相当了解的。

PS:JS中函数参数是没有默认值的。


补充回答:

JS中可以通过原型链继承来做到你想实现的效果:

function A(name) {
    this.name = name;
    this.a = 'I am A';
}
A.prototype = {
    hi : function() {
        console.log(this.name);
    }
};

function B(name) {
    this.b = 'I am B';
    // 这句是关键,创建A对象,并放到B对象的原型链上
    this.__proto__ = new A(name);
}

var b = new B('bbb'); // {b : 'I am B'},里面没有父类A的相关信息
b.hi(); // bbb
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号