一道关于原型链继承方面的js面试题
Javascipt中关于继承实现的关键是prototype
机制,正确的理解原型链机制可以帮助我们在复杂的场景下解决关于继承的一些问题。下面摘取了来自segmentfault上的一道关于原型链继承方面的面试题,深入分析如何正确的使用原型链实现继承。
题目如下:
1 | //片段1: |
分析:
1 | // 片段2 |
由题目可知,题目的目的在于对原型链的理解。关键在于子类B如何获得自己的实例属性和原型上的属性。代码片段2相信大家都比较熟悉,一段非常经典的关于原型链继承的实现代码。B通过在构造函数中调用A.call(this)
获取到父类A
的实例属性,通过B.prototype = Object.create(A.prototype);
获取父类的A
的原型属性,从而实现继承的目的。代码片段1如果要达到最后的输出效果应该将B操作为和片段2中的B一样的实例属性和原型属性。转换的关键包括:
- A函数直接调用
extend
接口,该接口如何添加 extend
接口中传入了一个对象,对象中包含了两个函数,say函数按照常理来讲应该作为B的原型属性添加在B的prototype
原型对象上。initialize
函数用来处理B的实例属性,包括将total
作为实例属性添加在自己的构造函数中以及在B的构造函数中调用父类A
的构造函数。
补充代码如下:
1 | Function.prototype.extend= Function.prototype.extend || function(obj) { |
如上所示,补充代码做了以下工作:
A
作为Function
的实例存在,因此如果A可以直接调用一个函数的话,可以将该函数作为原型属性添加在Function
的原型对象中。- 临时函数
SubClass
的构造函数中添加了superclass
属性,用来保存A
的this
值,用于后面obj.initialize
调用时,A
构造函数的调用。obj.initialize.call(this)
的调用保证了将total
属性作为实例属性添加在SubClass
的构造函数中,从而返回给B
。 SubClass.prototype = new self();
保证了SubClass的实例将继承A
的实例属性和原型属性。- 依次遍历参数中除
initialize
属性外的其他属性,并将其添加在SubClass
的prototype
上,并返回给B。
经过这样的处理后,运行var b = new B()
,此时实例b包括以下属性:
1 | name: 'apple' // 来自于obj.initialize.call(this) |
一道关于原型链继承方面的js面试题