1. ES6 以后 JavaScript 提供了 class,因此前端面向对象实现的一些功能都是基于 class 了,有 class 的代码相比于没有 class 的代码会更加直观、易懂
2. 更为常用的继承方式是组合继承(原型链+构造函数)以及 寄生组合继承
之所以有组合继承,是因为原型链继承的方式和构造函数继承的方式都会存在一些问题,这里提一个文章当中没详细讲的内容,就是对象寻找某个成员的过程,比如我们要在一个 Book 对象中寻找 name 这个属性,首先会在当前 Book 对象中寻找 name,没找到就会去到 Book 的 prototype,也就是原型中寻找 name,如果还没有,会继续在 Book 的基类对象中寻找 name,然后没有的话会去到 Book 的基类对象的原型中寻找,以此类推。原型其实也是对象,一般多个同类对象会指向同一个原型,在原型链继承的模式中,基类原型里面的属性都是被所有对象共同 shared 的,这里,你可以把原型里的成员对比理解成是 Java 类中的 static 成员:),但是我们并不想这样,我们希望每个对象能有自己唯一的成员,于是有了构造函数继承的方式,这里等同于,对于任意派生类对象,都完完整整 copy 一份基类对象,完全不用原型来继承,但是你又会发现这里其实是有资源浪费的,对于一些 getName() 这样的函数成员,没有必要 copy 多份,因此我们可以将原型链继承的方式和构造函数的方式结合起来,将需要 share 的部分用原型链的方式继承,需要独有的部分用构造函数的方式继承,这也就是组合继承的方式,另外寄生组合继承也是基于组合继承进行一个小小的优化,本质还是一样的
最后提一个细节的问题,文章中第二个代码块中的 setName 函数中的 name 定义前并没有加 var 或者是其他变量定义符修饰,在正常的函数中,name 会成为全局变量,为什么在这却不是这样的?
谢谢老师
展开
作者回复: 因为这个 name 是 Book 的入参:function Book(name),它的优先级更高。如果你在 setName 里面赋值给一个 Book 入参中没有定义的变量,比如 name2,那么它就会成为window.name2,也就是你说的“全局变量”。