https://www.cnblogs.com/sandraryan/
类的继承
要求构造函数首字母大写,便于区分构造函数和普通函数
编程过程中有一批数据有相同的属性和行为,为代码不冗余,让编程更有效率。将这些属性和行为封装起来,称为类(实际上还是函数)。
然后通过特殊方法调用函数,拿到返回值和具体的对象。
类为什么要继承
A类和B类有相同的行为属性,单独封装代码冗余,产生了继承,讲共同的单独封装在一个C类中,通过代码让AB和C建立联系。
从A B中实例化的对象都能使用C的行为。就称AB类继承了C类。
例如 数组和字符串都有length indexOf等方法。
call apply
不是为继承而生,但过于强大而被用于继承。。
var a = 'aaaaa'; var tom = { name:'tom', run: function(){ console.log(this.name + ' is running'); // tom可以访问a // run能直接访问的只有tom里面的 } }; // run(); 掉的是window下的run(),并不存在 tom.run(); var jery = { name: 'jery', run: function(){ console.log(this.name +' is running'); } } jery.run(); jery.run.call(tom);
jert.run.apply(tom);
jery.run.call(tom); 调用的是jery的run,但是用了call(tom),使jery里的this指向变成tom
call apply是js为函数提供的函数;(就像push是为array提供的一样)
当一个函数调用了call和apply后,函数中的函数体代码会执行。
函数中this的指向会变成call 和apply的第一个参数(this指向)
如果调用了call apply的执行需要传参,传给call apply。
call接受函数挨个传递
apply接受以数组形式传递
var jery = { name: 'jery', run: function(t,f){ console.log(this.name +' is running by' + t + f ); } } jery.run.call(tom,'leg1',' leg2'); jery.run.apply(tom,['head1',' head2']);
call apply实现继承
function Animal(kind){ this.kind = kind; this.speak = function(){ console.log('i can speak'); }; } // 原型方法 Animal.prototype.run = function(){ console.log('animal'); } // function Dog(name){ // var that = this; // Animal.call(that,'doggy'); // this.name = name; // } // 简化代码 function Dog(name){ Animal.call(this, '柴柴'); this.name = name; } var d = new Dog('柴柴'); console.log(d);
call 和apply函数可以实现继承,但只能i继承父类的公有方法和共有属性,无法继承原型的方法和属性
拷贝继承
拷贝继承只能继承父类原型的方法和属性,因为只对prototype做了拷贝
原型赋值继承
原型赋值继承也可以实现继承效果
这种继承只能继承原型
这种继承其实是让子类的prototype和父类的prototype指向了同一存储空间。
如果继承后再对子类原型做操作,父类原型也会被改变。不推荐
原型继承的真正方式
function Animal(kind){ this.kind = kind; this.speak = function(){ console.log('speaking'); }; } Animal.prototype.run = function(){ console.log('running'); } Animal.prototype.speak = function(){}; Animal.prototype.sleep = function(){}; function Dog(name){ this.name = name; } Dog.prototype = new Animal('狗'); var d = new Dog('tom'); console.log(d); console.log(d.kind); d.speak(); d.run();
从父类中实例化出一个对象,赋值给子类的prototype,既能继承到共有属性和方法也能继承到原型
但会导致constructor指向型错误,需要重新设置子类的constructor的指向
constructor指向这个对象的构造函数
原型链
假如有四个类ABCD,B继承A, C继承B,D继承C,
从D中实例化出一个对象,这个对象的_proto_指向D的prototype
_proto_的_proto_指向C的prototype,以此类推
原型链的产生是因为形成了继承链