在JavaScript的原型链继承方式中,为什么子类在调用父类的构造函数时不能传参数?

教程上说子类的构造函数需要父类的实例作为自己的prototype,但在调用父类的构造函数时参数列表必须为空,请问这是为什么?我试了一下传参,没有出现问题,参数也能正确起作... 教程上说子类的构造函数需要父类的实例作为自己的prototype,但在调用父类的构造函数时参数列表必须为空,请问这是为什么?我试了一下传参,没有出现问题,参数也能正确起作用。希望高人解答! 展开
 我来答
wang_family
2012-08-24
知道答主
回答量:10
采纳率:0%
帮助的人:5.7万
展开全部
我认为,不是不能给父类构造函数传参数,而是传的参数最终不能起到作用。举个例子:

function Parents(ln) { this.lastName=ln; } //定义父类构造函数
function Children(fn,ln) { this.firstName=fn; } //定义子类,lastName 继承自父类
//原型链继承,给父类构造函数传入参数,试图用 Children 类构造函数中传入的 ln 初始化 lastName:
Children.prototype=new Parents(this ln);
//尝试建立对象实例:
var child=new Children("Bill","Gates");
//输出结果。很明显,lastNmae 并没有得到想要的值:
alert(child.firstName);//Bill
alert(child.lastName);//Undefine

这说明给父类构造函数传递参数是无效的。原因就在于原型链方式中,调用父类构造函数的代码并不在子类构造函数中,建立对象实例时给的属性值(即子类构造函数的参数)并不能影响到子类调用的父类构造函数。
当然,在继承时可以这样写:

Children.prototype=new Parents("Gates");//调用父类构造函数时给固定值

但是,这个固定的属性值必定会影响所有子类的对象实例,相当于子类构造函数“擅作主张”给所有对象实例的属性提前“赋了值”。这样写是不太符合面向对象编程的规则的。
百度网友4f3fc44
推荐于2017-11-25 · TA获得超过3003个赞
知道小有建树答主
回答量:659
采纳率:50%
帮助的人:350万
展开全部
以前我在看书时也遇到过这样的问题,找了很多资料都没有明确的解释。
我觉得,并不是语法上不能实现对构造函数的参数传递,而是这样做不符合面向对象编程的规则:对象(实例)才是属性的拥有者。
如果在子类定义时就将属性赋了值,对象实例就不能再更改自己的属性了。这样就变成了类拥有属性,而不是对象拥有属性了。
举个例子,子类 Children 继承父类 Parents,Parents 构造函数:
function Parents(name){ this.name=name; }
使用原型链并给父类构造函数传参数:
Children.prototype=new Parents("Hello");
那么此时,Children 类就拥有了 name=“Hello” 属性,而 Children 类的实例对象 c1、c2、c3 等等只能被迫接受这个 name 属性。Children 是 "Hello" 的拥有者而 c1、 c2、c3不是!
如此写完全失去了面向对象编程的意义,所以在原型链继承方式中规定不能对父类构造函数传递参数。也因为这个原因,原型链继承方式并不实用。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
kongfanhefrank
2017-08-19
知道答主
回答量:1
采纳率:0%
帮助的人:956
展开全部

WANGERN 的答案很有启发, 我接着他回答, 我也是新手, 这只是我的理解, 希望牛人来指正:

并不是语法上不能实现对构造函数的参数传递,而是这样做不符合面向对象编程的规则:对象(实例)才是属性的拥有者。如果在子类定义时就将属性赋了值,就变成了类拥有属性,而不是对象拥有属性了。 举个例子,

function Parent(name){ this.name=name;}
function Child(age){this.age=age;}
Child.prototype=new Parent("Hello");
var c1= new Child(1);
alert(c1.age+'...'+c1.name);

此时Child类是"Hello"的拥有者, 而Child类的实例对象c1不是. 如此写完全失去了面向对象编程的意义. 但是在"避免类拥有属性值"这一前提下, 还是可以这样修改的:

function Parent(name){this.name=name;}
function Child(age){this.age=age;}
Child.prototype = new Parent();
var c1= new Child(1);
c1.name='Hello';
alert(c1.age+'...'+c1.name);

显然这样的代码也不够优雅, 因为需要初始化之后再设置name值, 代码被打散了. 于是自然想到将 Child 的实例化封装成函数.

function Parent(name){this.name=name;}
function Child(age){this.age=age;}
function createChild(age, name){
  Child.prototype = new Parent();
  var c=new Child(age);
  c.name=name;
  return c;
}
var c1= createChild(1, 'Hello');
alert(c1.age+'...'+c1.name);

可是, 本来规范的 new Child(name,age) 书写变成了 createChild(age, name), 代码还是不优雅. 于是就有了 "对象冒充+原型链继承" 的 "组合模式":

function Parent(name) {this.name = name;}
function Child(age,name){Parent.call(this,name);this.age=age;}
Child.prototype = new Parent();
var c1= new Child(1, 'Hello');
alert(c1.age+'...'+c1.name);

代码变得优雅了一些. 但也不是绝对. 所以, 因为JavaScript语法的灵活(不伦不类), 事实上继承的实现方式有很多, 也并不存在绝对无法传参数的问题, 只不过组合模式代码相对优雅, 而广泛采用. 说到底, 对象冒充一开始也不是ECMAScript官方认定的继承方式. 此问题本身就是灰色地带.

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式