在了解js原型链之前构造函数、原型对象、对象实例这几种概念必须要明白。
1. 创建对象有几种方法
//原型链指向object
var o1={name:'o1'}; var o11=new Object({name:'o11'});//通过new来声明对象
var M=function(){this.name='o2'} //使用显示的构造函数创建对象 var o2=new M();
var P={name:'o3'}; var o3=Object.create(P)
每个对象都有一个__proto__属性,指向这个对象的构造函数的原型对象。
2. 构造函数和普通函数的区别
(1)构造函数内部会创建一个新的对象实例;函数内部this指向新创建的实例;默认的返回值是f的实例。
(2)在调用函数的内部不会创建新的对象;this指向函数调用的对象,如果没有对象调用,默认是window;返回值由return语句决定。
3. 原型对象
在声明一个函数的时候就会有prototype属性,就是原型对象,原型对象内部包含一个constructor属性,指向构造函数本身。
4. 构造函数、原型和实例的关系
每个构造函数都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型对象的内部指针(__proto__)。
构造函数----prototype原型对象-----__proto__---原型对象。
5. 原型链
当调用某种方法或者查找某种属性时,首先会在自身查找和调用,如果自身没有该属性或方法时,则会去他的__proto__属性中去查找,也就是去他的构造函数的原型对象中去查找。
如果我们让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针,此关系层层递进,构成实例与原型的链条。例子:
function Type(){ this.proporty = true; } Type.proptotype.getValue = function(){ return this.proporty; }
function SubType(){ this.subproporty = false; } // 继承了Type SubType.prototype = new Type(); SubType.prototype.getSubValue = function(){ return this.subproporty; } var result = new SubType(); alert(result.getValue()) // true
以上代码分别定义两个类型,每个类型分别有一个属性和方法。它们的主要区别是subType继承了Type,而继承是通过创建Type的实例,并将改实例赋给subType.prototype实现的。实现的本质是重写原型对象,代之以一个新的类型的实例。
也就是原来存在于Type实例中所有的属性和方法都被SubType继承。
最终,result指向subType的原型,而SubType的原型又指向Type的原型。
6. 继承
原型链是实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
最后,两个相等
function Fn(){}
var f = new Fn()
实例的隐式原型(__proto__)指向它的构造函数的显示原型(prototype)即 f.__proto__=== Fn.prototype // true
构造函数的原型里有一个constructor属性指向构造函数本身 即 Fn.prototype.constructor === Fn //true