序:
虽然知道java和JavaScript没有什么关系,但是在了解JAVA后学习JavaScript时,还是忍不住将这两者对比,因此通过总结来更好的了解继承这一特性。
Java:面向对象的语言
JavaScript:面对过程的语言实现
继承:
1 JAVA:一般通过创建父类子类 并通过extends关键字来实现父类与子类的多继承关系
class Father(){
}
class Son extends Father(){
}
2 JavaScript:作为面对过程的语言,为实现继承只能通过模拟面对对象的方法,导入原型这一概念来模拟继承。
首先总结几个概念:
1)通过构造函数创建对象
class Car(name,ability){
this.pname=name;//公有属性
this.pability=function ability(){};//公有方法
var sec="11";//私有属性
//特权函数
(在js对象中能够用来访问内部局部变量的函数,特权函数实际上也是公有的,只不过特殊之处在于能够读写私有属性)
this.getSecret = function () {return secret;};
this.setSecret = function (newSecret) {secret = newSecret;};
}
//JS中通过new 构造函数可创建对象,且只有构造函数才能 new一个函数
var car1=new Car()
构造函数中的公有私有方法属性:
公有:对象中的属性和方法,在对象外部能够直接访问
私有:对象中的属性和方法只能在对象内部访问,在对象外不能直接访问。需要通过特权函数
2)什么是原型prototype
prototype:js给函数提供了一个对象类型的属性,叫做Prototype原型,每个函数都有一个prototype属性,类型是一个对象。原型归函数所有,他不用创建,是默认存在的。
出现原因:为了解决js模拟面对对象时,一些【共同拥有的属性】而出现的问题。
本质:原型的存在是为了给类的对象添加公有属性。
function People(pname){
this.pname=pname;
}
People.prototype.eyesNum=2 ;
var frank = new People('张先森');
console.log(frank.pname);//张先森
console.log(frank.eyesNum);//2
/*
frank对象中只有name这一个属性,但是可以通过构造函数的原型访问到原型中的属性
查找属性的原则:如果是通过类创建的对象,当访问的属性在对象中如果没有找到,则会去【创建对象的类】的原型中查找,如果找到,也相当于对象拥有这个属性。
**/
3)原型链是如何实现继承的
每个函数的原型(对象)中有两个默认的属性:
1.**构造器constructor:**该属性指向了类本身
2.****proto: ****指向原型本身,提供给【类创建的对象】使用:通过对象可直接访问创建该对象的类的原型。
构造器:
function People(){};
console.log(People.prototype.constructor);
// People(){}
原型指向:输出的内容是【frank对象的构造函数frank的原型】People.porptotype
var frank = new People();
console.log(frank.__proto__);
//[constructor: ƒ]{
constructor:f People();
_proto_:Object
}
缺点:原型中不能保存数组这样引用类型的数据,因为地址传递的问题会导致出现修改的连锁变化.
引用类型:
function People(){}
var peo1 = new People();
var peo2 = new People();
People.prototype.girlFriends = ['lily','lucy','sophia','sara'];
//第一个人把四个女朋友的最后一个甩了,留仨;第二个人不受影响还是四个女朋友
//第一个人把四个女朋友的最后一个甩了,留仨;第二个人也甩了最后一个,剩仨。
peo1.girlFriends.pop();
console.log(peo1.girlFriends);
console.log(peo2.girlFriends);
非引用类型
function Car(){}
var mycar1 = new Car();
var mycar2 = new Car();
//使用原型能够有效的节约内存空间,令所有对象都享有这个属性
Car.prototype.lun1 = '车的第一个轮子';
//这里的修改实际上是给对象内部添加的公有属性,对原型中的属性没有影响
mycar1.lun1 = '防滑轮胎';
mycar2.lun1 = '赛车轮胎';
console.log(mycar1);
console.log(mycar1.lun1);
console.log(mycar2);
console.log(mycar2.lun1);
继承:Js可以模拟面对对象中的继承关系,通过原型的方式解决
原型链构成:
A 描述:
【对象的__proto__属性】和【对象的构造函数的原型的__proto__属性】构成的链式结构称为原型链。
B 白话:
对象的原型,跟他父类的原型绑在一起,拧成一根链子。那么这根链子就称为原型链。
C 注意:
(1)原型链的顶端是Object
(2)Object类的原型(Object.prototype)没有__proto__属性。
D 作用:
访问对象的属性的时候,先在对象本身中查找;
如果在对象中没能找到这个属性,则会沿着原型链逐级向上查找,
在原型链的任何一级如果找到这个属性,都视同对象拥有这个属性。-------被称为是【继承】
E 构建:
设置子类的prototype属性是父类的实例,即可构建原型链
例子:
function Father(){}
Father.prototype.money = '数不清';
var mayun = new Father();
//创建一个类,并将prototype属性赋值为Father类的一个对象
function Son(){}
Son.prototype = mayun;
//创建一个Son类的对象
var frank = new Son();
console.log(frank.money);//数不清
图解1
图解2(理解完书里的内容在添加)
总结:
1 继承只是一个思想,任何语言都可能具有,只是表达的形式,使用的原理不同。理解时应尽量减少受到别的语言的影响。
2 通过同一类创造的对象既需要给指定类型赋不同的值,即公有属性,同时需要给指定属型赋相同的值,为了避免每新建一个对象,就要赋一个相同的值这样的冗余操作以及占用内存,因此引入原型概念来代表对象的公共的公有属性。
3 因为某个对象(实例)的属性除了可以在这个对象中查找也可以在创造这个属性的类的原型中查找,则根据原型是个对象这一特性,则可以给类的原型重新赋值一个实例,从而通过原型的属性的特性关联到了这个将新赋的实例通过它的原型可以查找到,并将其类作为父类,通过父类的原型,得到父类的属性和方法以实现继承关系。