菜鸟快飞之JavaScript对象原型继承

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了菜鸟快飞之JavaScript对象原型继承相关的知识,希望对你有一定的参考价值。

  正文之前需要声明的一点是,菜鸟系列博文全是基于ES5的,不考虑ES6甚至更高版本。

继承

  由于我个人不是学计算机的,所以对于很多东西只是知其然,不知其所以然。就像这个继承,刚开始学javascript就听人说了JavaScript几大核心,但是自己平时似乎都没怎么用到,所以一直不明白为什么需要这些东西,面试还总是问这些。

  但是随着一点点学习,也有去看过jQuery源码,虽然到现在也没怎么看懂(主要也是有些懒),但慢慢还是对这些东西有了更深的了解。

为什么需要继承 

  举个很简单的例子,我在平时学习写一些页面的时候,里面的代码很少,而且更多还是用jQuery去写的,若非是专门为了练习JavaScript,否则根本用都用不上。

  但是这只是一些很小的东西,如果你需要写一个jQuery这样的库呢,angular这样的框架呢,那么你必然会需要大量的优化你的代码,让能够写一次就解决的东西尽量不要再写第二次,否则几千行能写完的东西,你可能需要写上万行才行了。

  这个时候继承就是一个很好的解决方法,让一个子类能够拥有父类的属性和方法,同时子类也能拥有自己的属性和方法。

  所以什么是继承,就是让一个子类拥有父类的属性和方法,自己不用再去重复写一次。

原型链

  JavaScript和其他语言不同,没有类,也就是class,所以不能用常规的方式实现继承。但作为一门面向对象的语言,JavaScript有其独特的实现方式——原型链。

  之前说过,每个函数都有一个原型对象prototype,每个实例都有一个指向原型对象的内部指针__proto__。

 

function Fun(){}

var fun1 = new Fun();

 

  fun1.__proto__ ----> Fun.prototype.__proto__  ----> Object.prototype.__proto__  ----> null

 

 

  让一个类型的原型对象等于另一个类型的实例:

 

function Fun() {

}

function Sub() {

}

Sub.prototype = new Fun();

Sub.prototype.__proto__ === Fun.prototype; // true  

var sub1 = new Sub();

 

  sub1.__proto__ ----> Sub.prototype.__proto__ ----> Fun.prototype.__proto__  ----> Object.prototype.__proto__  ----> null

 

  这样就形成了一条原型链,通过原型链,我们便可以实现继承,让子类拥有父类的属性和方法了。

function Fun() {
    this.name = ‘Mike‘;
    this.age = 10;
    this.sayHello = function() {
        console.log(‘Hello! 我叫‘ + this.name + ‘今年‘ + this.age + ‘岁‘);
    };
    this.nums = [1,2,3,4];
}

function Sub() {

}

Sub.prototype = new Fun();

var sub1 = new Sub();    
sub1.sayHello(); // Hello! 我叫Mike今年10岁 
sub1.name = ‘Jarry‘;
sub1.sayHello(); // Hello! 我叫Jarry今年10岁 

var sub2 = new Sub();
sub2.sayHello(); //Hello! 我叫Mike今年10岁 
sub2.nums; // [1,2,3,4]

sub1.nums.push(6,7);
sub2.nums;  // [1,2,3,4,6,7]

  但是单独使用原型链来继承会存在问题,就像上面的代码一样。

  我们知道,通过原型链的方式,父类的方法和属性都是在子类的原型链上,原型链上的方法和属性是会被实例共享的,所以当一个引用类型的值被一个实例改变后,另外一个实例再次调用的时候,其值也会发生改变。而且还有个问题就是参数传递不方便。

组合继承

  为了解决上面的问题,我们在原型链的基础上加上一些其他东西,call()或者apply().

function Fun(name,age) {
    this.name = name;
    this.age = age;
    this.sayHello = function() {
        console.log(‘Hello! 我叫‘ + this.name + ‘今年‘ + this.age + ‘岁‘);
    };
    this.nums = [1,2,3,4];
}

function Sub(name,age) {
    Fun.apply(this,arguments);
}

Sub.prototype = new Fun();

var sub1 = new Sub(‘小红‘,10);    
sub1.sayHello();

var sub2 = new Sub(‘小明‘,20);
sub2.sayHello();

sub1.nums.push(6,7);
sub1.nums; // [1,2,3,4,6,7]
sub2.nums; // [1,2,3,4]

  这样问题就解决了,这个模式也是现在使用最多的模式,当然还有一些其他的,比如原型式继承,寄生式继承,但是我也还没弄明白他们的具体优点,希望有知道的前辈、朋友,能够提点一下,小子非常感谢!!

 

  

   

  

以上是关于菜鸟快飞之JavaScript对象原型继承的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript高级原型和继承相关:原型对象函数原型原型链和继承继承的优化对象判断相关方法

JavaScript高级原型和继承相关:原型对象函数原型原型链和继承继承的优化对象判断相关方法

Javascript继承4:洁净的继承者----原型式继承

JavaScript之面向对象学九(原型式继承和寄生式继承)

Javascript继承6:终极继承者----寄生组合式继承

JavaScript——面向对象原型继承与class继承