历史来源:
Brendan Eric负责开发——>正值面向对象编程最为兴盛的时期,故而收到影响,Javascript里面所有的数据类型都是对象——>JS它必须要设计成一种简易的脚本语言,所以Brendan Eric没有引入“类”,JS并不需要成为一种完整的面向对象编程语言,那与它的设计初衷相悖——>那么如何将这些对象联系起来呢?Brendan Eric设计了“继承”机制。
new运算符:
在C++和Java中,都是用new来实现,所以在JS这里new也被设计到继承中去。
Brendan Eric做了一个类似于面向对象语言的“继承”,在new的后面是构造函数。
function People(name){
this.name = name ;
}
let Bob = new People('Bob');
console.log(Bob.name) ;
但是问题也随之而来,当我们还需要Lily,Tom,David……的时候,我们无法共享属性与方法。将这些个对象new出来后,他们的属性和方法之间相互独立,就像平行线一样。
这样数据无法共享,造成资源浪费。
prototype属性
为了解决上述问题,引入了prototype属性。该属性包含一个对象,所有需要共享的属性和方法都放在这个对象里面;那些不需要共享的属性和方法就放在构造函数里面。实例对象一旦创建,将自动引用prototype对象的属性和方法。所以,实例对象的属性和方法就分为两种,一种是本地的,另一种是引用的。
function People(name){
this.name = name ;
}
People.prototype = { sex: '男'} ;
let Bob = new People('Bob') ;
let David = new People('David') ;
console.log(Bob.sex);
console.log(David.sex);
prototype对象就好像是实例对象的原型,而实例对象就好像“继承”了prototype对象一样。
原型链
prototype原型对象又有自己的原型,直到某个对象的原型为null为止,也就是说至此没有原型指向。这种一级一级的链结构就称为原型链。就像我们的父辈->我们父辈的父辈->我们父辈的父辈的父辈…世界上第一个人->不是人的东西。
基于原型链的继承
- 继承属性:
JS对象有一个指向一个原型对象的链。当访问一个对象的属性时,不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,就这样层层向上搜索,直到找到一个名字匹配的属性或到达null。
举个例子:
假如有一个对象A,它有属性{x:1,y:2}
A的原型B,有属性{z:3,w:4}
A的原型:A.prototype;
B的原型:B.prototype;
console.log(A.x);//1
console.log(A.z);//3
console.log(A.d);//undefined
创建一个对象它自己的属性的方法就是设置这个对象的属性。
- 继承方法:
JS并没有“方法”,任何函数都可以添加到对象上作为对象的属性。继承类似上面。
var a = {
x:1,
y:function(){
return this.x+1;
}
}
console.log(a.y());//2
var b = Object.create(a);
b.x=10;
console.log(b.y());//11
当继承的函数被调用时,this指向的是继承的对象,并不指向继承函数所在的原型对象。
如何生成原型链
使用构造器创建对象
function Cat(){
this.children = [];
this.food =[];
}
Cat.prototype = {
addFood : function(f){
this.food.push(f) ;
}
}
var c = new Cat();
使用Object.create创建对象。上面有例子。
使用class关键字。ES6
use "strict";
class Box{
constructor(height,width){
this.height = height ;
this.width = width ;
}
}
class RedBox extends Box{\
constructor(length){
super(length,length);
}
…
}
var b = new RedBox(2);
JS原型链的性能
在原型链上面查找属性比较耗费时间,性能也不好,当我们查找一个根本不存在的属性的时候,会遍历整个原型链,原型链上的属性是可枚举的。
那我们如何检测某个属性到底是在自身还是原型链上?hasOwnProperty方法可以解决,这个方法继承自Object.prototype;是JS中唯一一个只涉及对象自身属性而不会遍历原型链的方法。
还发现一个特别有趣的讲解原型链的文章附上链接,诸位看官可到此一游。
简单粗暴的理解JS原型链