1、原型继承:闭包
1、提及原型继承,就要先由构造函数创造对象提及,首先了解构造函数内部基本原理:app
(1).在函数体最前面隐式的加上this = {}函数
(2).执行 this.xxx = xxx;this
(3).隐式的返回thisspa
而且要注意隐士建立的this对象中有个名为__proto__的属性,其属性值为该构造函数继承的原型prototype。prototype
而原型对象的有一个名为constructor的属性,其属性值为继承之的构造函数,code
因此能够经过这两个属性相互查看对象
2.原型的定义及一些特色:blog
a.定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。经过该构造函数产生的对象,能够继承该原型的属性和方法。原型也是对象。继承
b.利用原型特色和概念,能够提取共有属性。
c.对象如何查看原型 — > 隐式属性 __proto__
d.对象如何查看对象的构造函数 — > constructor
三、若一个构造函数没有指定其原型,则其原型默认为Object.prototype
2、原型链:
1.原型的造成,最好的解释就是代码了,看以下代码便可
A.protorype = { name: 'a' } function A() ( this.name = 'A'; ) B.prototype = new A(); function B() { this.name = 'B'; } C.prototype = new B(); function C(){ this.name = 'C'; } C继承B,B继承A,造成C->B->A的一条以原型为继承方式的原型链
二、原型链上属性的增删改查:
(1)查:优先去实例对象上寻找是否有该属性,若没有,则再去其对应的原型上去寻找该属性,若都没有,则返回undefined
(2)增:直接给实例对象增添属性,则仅仅在实例对象上增添属性,若在原型上增添属性,则在原型上增添属属性,则在原型上增添属性,其实例继承原型增添的属性。
(3)删:delete仅仅能删除实例对象的属性,即构造函数原有的本身的属性和后来实例对象增添的属性,还有关于delete的一点需注意,delete没法删除原型的属性和用var定义的变量(即非window的属性)
(4)改:更改实例对象的属性,则仅仅更改实例对象的属性值;更改原型的属性值,则更改原型的属性值,继承该原型的对象对应属性值也会被更改;
3、对象继承的发展:
一、传统模式:即正常的经过构造函数建立实例对象,来继承原型
缺点:继承了过多没必要要的属性
二、借用其余构造函数(即经过call / apply来改变构造函数内this对象的引用)
缺点:没法继承借用构造函数的原型
A.prototype = { name: 'a', age: 18, class: 1 } function A(){ this.name = 'A'; } function B(){ A.call(this); } var b = new B(); console.log(b.name); // A console.log(b.age) // undefined
三、共享原型:即将其余构造函数的原型直接赋值给本构造函数的原型
缺点:两个原型会想回影响,更改其中一个原型,更一个对应的原型也会被更改。
A.prototype = { name: 'a', age: 18, class: 1 } function A(){ this.name = 'A'; } B.prototype = A.prototype; function B(){ this.name = 'B'; }
C.prototype = A.prototype;
function C() {
this.name = "C";
}
var a = new A(); var b = new B();
var c = new C(); console.log(a.age); // 18 console.log(b.age); //18
console.log(c.age); //18
// 原型继承成功 B.prototype.age = 20; //更改其中一个原型的age属性 console.log(b.age);//20 console.log(c.age); //20 // 继承A原型的B和C相互影响
四、圣杯模式:
每次继承的都是新建立的F构造函数实例,相互之间不会影响。其实此处针对F造成了闭包,Child引用了F,致使F不会销毁。
(1)正常函数形式:
function inherit (Child, Parent) { // 借用F这个中间量来继承,而不是直接共享原型 var F = function (){} F.prototype = Parent.prototype; Child.prototype = new F(); // 自定义构造函数原型时,同时要更正自定义原型的constructor,不然通常默认为Object(),次函数若不指定constructor,则constructor为Parent Child.prototype.constructor = Child; Child.prototype.uber = Parent; //记录真正继承的是谁 }
(2)闭包形式:
var inherit = (function(){ var F = function (){}; return function (Child, Parent) { F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.prototype.uber = Parent; } })();