前端面试之3-11 面向对象(一)

这块考察主要两种方式,一是直接问,面向对象的相关知识点,比如类与实例,类与继承。

前端面试之3-11 面向对象(一)_第1张图片

还要一种问法,一个对象,继承了某个类,问你它的原型链。这块已经是上一节课讲述的内容。在一个对象上找不到一个属性,会沿着原型链往上找。


前端面试之3-11 面向对象(一)_第2张图片
前端面试之3-11 面向对象(一)_第3张图片

下面讲类的继承:

实现继承的基本原理,就是前面讲的原型链,继承本质就是原型链。js继承有几种形式,每种形式有哪些优缺点。如果问道面向对象,继承必问,继承方式必问。有什么不同点。其实考原型链的掌握程度。


前端面试之3-11 面向对象(一)_第4张图片

先写一个父类Parent1,有个名字属性。写一个子类,子类的构造函数Child1 ,子类也增加一个属性。增加属性之前,通过构造函数来实现继承,既然实现继承,要体现parent1哦,所以在子类的构造函数里面执行父类的构造函数。就是Parent1.call(this),这样就实现了一个继承。call和apply都可以用,改变了函数运行的上下文。通过这种调用,在子函数中执行,同时修改了this的指向,也就是指向了Child1类的实例化的对象的引用。从而导致了父类的执行时,这个this属性,挂载到child这个类的实例对象上去。

前端面试之3-11 面向对象(一)_第5张图片

新生成的对象,有了父级元素的name属性,实现了继承。写出来后,问你为什么能实现继承,主要原理就在40行。将父级构造函数的this指向子构造函数的实例上去。导致父级构造函数的所有属性,子类中也有。

借助构造函数实现继承缺点是什么?

Parent1也有自己的原型链和prototype,如果说Parent1除了构造函数里面的内容(这里就是this.name),还有来自原型链上的东西。这样的继承是为了改变this的指向,但是parent1原型链上的东西,并没有被child1所继承。

如果打印出say方法,会报错,就是因为没有继承父类原型对象上的方法。所以这种方式可以实现继承,但是只是部分继承,如果父类的属性都在构造函数里面,那么没有问题, 但是如果父类原型对象还有方法的话,子类是继承不到的。

前端面试之3-11 面向对象(一)_第6张图片


第二个方法就是弥补构造函数的不足,借助原型链实现构成。

前端面试之3-11 面向对象(一)_第7张图片

重点在55行。Child2.prototype 这里的prototype是子构造函数的属性。这个属性,是一个对象,这个对象可以任意赋值的。现在赋值给父类parent2的一个实例。new Parent2()是一个对象,这个对象给了Child2的prototype属性。57行,实例化了Child2,生成一个新的对象。新的对象有个_proto_属性,等于Child2的prototype对象。Child2的prototype对象被赋值为Parent2父类的一个实例。按照作用域的寻找方式,先找new Child2() 也就是s1 上面的属性,比如说找name,通过Child2实例化的属性上没有name,这个作用域就开始找新的对象有个_proto_属性,也就是Child2的prototype对象,同时又是Parent2()的一个实例,父类的实例,当然就有了name属性。就找到了父类的对象,父类的对象上,已经有name了。所以就是能拿到这个name,实现了继承。


前端面试之3-11 面向对象(一)_第8张图片

这个继承方式有什么缺点:

新建s1,s2,打印出来,1,2,3。但是如果s1添加了一个4,那么s2也改变了。可是这两个实例应该隔离的,造成原因是因为原型链中的原型对象是共用的。


前端面试之3-11 面向对象(一)_第9张图片

因为s1._proto ===s2._proto_  这是这种继承方式的缺点。

详细内容可以参考《JavaScript高级程序设计》164-167页。

你可能感兴趣的:(前端面试之3-11 面向对象(一))