一.原型对象
对象分为:
- 普通实例对象
- 函数对象
1 //函数对象Person 2 function Person(name){ 3 this.name = name; 4 } 5 console.log(Person.prototype); 6 7 //实例对象person1 8 var person1 = new Person(); 9 console.log(person1.__proto__);
结论:
-
函数对象的prototype属性就是原型对象,原型对象也是一个实例对象。
-
函数对象有prototype属性,实例对象有__proto__属性。如果属性前面和后面都有两个下划线则该属性为私有属性不可以修改。
-
函数对象的prototype属性等价于实例对象的__proto__属性。
-
函数对象的prototype属性也称为显示原型对象,实例对象的__proto__属性也称为隐式原型对象。
-
原型对象的constructor属性指向函数对象本身
二.原型对象的作用
减少内存开销,方便添加属性
1 //函数对象Person 2 function Person(name,age){ 3 this.name = name; 4 this.age = age; 5 this.eat = function(){ 6 console.log("eat"); 7 } 8 } 9 10 Person.prototype.play = function(){ 11 console.log("play"); 12 } 13 14 //原型对象 15 var person1 = new Person(); 16 var person2 = new Person(); 17 18 console.log(person1);
从图中可知:在Person声明时定义eat方法和使用原型对象添加的play方法都保存了,但是eat方法存在于实例对象中,而play方法存在与原型对象中。如果实例对象越多eat方法就会被反复创建多份但play方法一直都只有一份保存在原型对象中。
注:Object的实例对象有constructor属性,没有__proto__属性(__proto__=null),如果一个实例对象调用方法没有找到会通过原型链继续查找直到找到Object中,若没有则没有此方法。
三.原型链
例1:
例2:
1 function f(name){ 2 this.name = name; 3 this.say=function(){ 4 5 } 6 } 7 8 f.xxx = "xxx"; 9 f.yyy = function(){ 10 11 } 12 13 f.prototype.hello = function(){ 14 15 } 16 17 var ff = new f("小明");
四.构造函数
1 function f(name){ 2 this.name = name; 3 } 4 5 //追加方式 6 f.prototype.hello = function(){ 7 8 } 9 10 console.log(f.prototype); 11 12 //重新指向方式 13 f.prototype = { 14 hello: function(){ 15 16 } 17 } 18 19 console.log(f.prototype);
第一个是使用追加方法添加方法,第二个是使用将指针重新指向方式会导致没有构造函数。
我们还原构造函数:
1 function f(name){ 2 this.name = name; 3 } 4 5 //追加方式 6 f.prototype.hello = function(){ 7 8 } 9 10 console.log(f.prototype); 11 12 //重新指向方式 13 f.prototype = { 14 hello: function(){ 15 16 } 17 } 18 19 //还原构造函数 20 f.prototype = { 21 constructor:f, 22 hello: function(){ 23 24 } 25 } 26 27 console.log(f.prototype);
五.原型链终极目标
从图中可知
-
Object的函数对象是由Function的函数对象创建出来的:Object.__proto__ === Function.prototype
-
Function的函数对象由自身创建出来的:Function.__proto__ === Function.prototype
-
所有的函数都是有Function的函数对象创建出来的:foo.__proto__ === Function.prototype === Function.__proto__
六.原型链与instanceof运算符
表达式:A instanceof B
如果B函数对象的显示原型对象(prototype)在A对象的原型链上(__proto__),返回true,否则返回false
例1:
1 function Foo(){ 2 3 } 4 5 var f1 = new Foo(); 6 console.log(f1 instanceof Foo); //true 7 console.log(f1 instanceof Object); //true 8 console.log(f1 instanceof Function);//false
解析:
- f1 instanceof Foo ::f1.__proto__ === Foo.prototype
- f1 instanceof Object:f1.__proto__.__proto__ === Object.prototype
- f1 instanceof Function:f1在隐式原型链上一直找到null 都没有找到与Funtion.prototype相同的对象
例2:
1 console.log(Object instanceof Function); //true 2 console.log(Object instanceof Object); //true 3 console.log(Function instanceof Object); //true 4 console.log(Function instanceof Function);//true