虽然在js中没有类,构造函数本质上也只是一个普通函数,new关键字调用一个构造函数来创建一个新对象,也是js在努力模仿面向对象语言中类new对象的实现,这个模仿过程也对开发者造成很大误导,但不能否认的是也降低了理解的门槛,在初期快速上手阶段还是很有帮助的。
至少我刚开始不是很明白js的原型链时,就是按照面向对象的类思路来写的,并且在js中也都可以实现js版的类、实例对象、成员属性、成员方法、继承、多态和封装,所以其实就当个面向对象的语言来写,在初期也是没什么问题的。但是在慢慢理解js与面向对象语言的区别后,虽然还是正常使用这些面向对象的标准概念,但本质还是要分清的,这对于迈向js精通是绝对必要。
上篇讲的是js的构造函数,也涉及到js的原型,而要想原型发挥作用,就必须要有个原型继承来承接:
1function Foo(name){
2 this.name = name;
3};
4Foo.prototype.showName = function(){
5 console.log(this.name)
6}
7var obj = new Foo("nitx");
8obj.showName(); // nitx
对象obj就是通过原型继承来关联到Foo.prototype
对象的。
那么上述实现过程用到原型继承,还有什么场景需要用到原型继承呢?
就是面向对象中的继承步骤。
js版的继承其实就是通过原型继承来关联到“父类”的,看下面代码示例:
1function Foo(name){
2 this.name = name;
3}
4Foo.prototype.showName = function(){
5 console.log(this.name);
6}
7function Bar(name, age){
8 Foo.call(this, name);
9 this.age = age;
10}
11Bar.prototype = Object.create(Foo.prototype); // 这行代码是实例子类继承父类的关键
12Bar.prototype.showAge = function(){
13 console.log(this.age);
14}
15var b = new Bar("nitx", 30);
16b.showName(); // nitx
17b.showAge(); // 30
上例用面向对象的概念解释就是子类Bar继承父类Foo,
但js版的理解是这样子的:注意看,Foo函数的原型对象通过Object.create()
方法创建一个新对象,这个新对象的[[Prototype]]
属性指向Foo.prototype对象,并且通过赋值操作符来修改Bar.prototype这个标识符原本指向的对象,改为指向刚才新创建的对象。所以这个过程,就把Bar函数原有的Bar.prototype对象给抛弃掉了。
所以这步操作的作用就是原型继承。至于Bar函数中的Foo.call(this, name);
,就是通过call关键字将Foo函数内的this对象绑定到Bar函数内的this对象上,从而借用Foo函数内作用域的执行代码为Bar函数执行时所用。这样就完成了一个模拟类继承的过程。
不得不说,这是一个天才般的设计,再次为Brendan Eich点个赞,上柱香,拜一拜~~~~
所以ES6中的class继承,其核心实现原理就是这样差不多,只是通过语法糖,来使之写起来和java面向对象写法一样,唔,但自己心里也拎的清,这个class
就是样子货罢了,不受你迷惑,不受你迷惑,不受你迷惑…
-------------------------------- 热门文章 --------------------------------
设计模式>>>