原型、原型链、构造函数是JavaScript比较难的知识点,但是它们又功能强大,是我们进行组件开发、模块开发必须掌握的技能,翻阅网上相关的博文,个人觉得这几篇博文不错,可以一读:
1)汤姆大叔:强大的原型和原型链
2)深入理解JavaScript系列(10):JavaScript核心(晋级高手必读篇)
3)三张图搞懂JavaScript的原型对象与原型链
4)Js中Prototype、__ proto __、Constructor、Object、Function关系介绍
5)前端基础进阶(九):详解面向对象、构造函数、原型与原型链
因此,本文不再大篇幅图文介绍JavaScript对象、原型、原型链、构造函数等知识点,而是力求用简单文字、代码输出剖析prototype、__proto__和constructor三者间的关系。
1、prototype和__proto__
- 1)prototype是函数(function)才有的属性;
- 2)__proto__是每个对象(object)都有的属性,指向对象构造函数的prototype;
var a = {}; // 等同 a = new Object();
console.log(a.prototype); //普通对象没有prototype属性,->undefined
console.log(a.__proto__); //构造函数原型, Object.prototype, ->Object{...}
var b = function(){}
console.log(b.prototype); //b {}
console.log(b.__proto__); // = Function.prototype, ->function() {}
说明:Function.prototype = function,是特例,下文会继续讲解。
- 3)__proto__构成原型链,Object.prototype.__proto __= null,原型链结束
var a = {};
console.log(a.__proto__); //=Object.prototype, ->Object {}
console.log(a.__proto__.__proto__); //=Object.prototype.__proto__, ->null
原型链从继承角度理解就是找父类,以Java为例:
1)a是一个普通对象实例,则a的父类是基类Object;
2)基类Object没有父类,因此可以理解其父类为null。
而JavaScript用原型链表示这种继承关系,用对象的__proto__属性构成原型链:
1)a.__ proto __ = Object.prototype
2)a.__ proto __ . __ proto __ = Object.prototype. __ proto __ = null
- 4)__ proto __,通常指向对象构造函数的prototype,有一种情况例外Object.create方式创建的对象。
var a1 = {};
var a2 = Object.create(a1);
console.log(a2.__proto__==a1) ->true
用Object.create(a1)创建的对象,其__proto__会指向a1,因此对于a2来说,其原型链为:
a2.__ proto __ = a1;
a1.__ proto __ = Object.prototype;
a2.__ proto __ . __ proto __ . __ proto __ = null
2、Prototype和Constructor
在 JavaScript 中,每个函数对象都有prototype属性,用于引用原型对象。prototype对象又有隐藏属性constructor,它反过来引用函数本身,是一种循环引用。
function Animal(){
}
var anim = new Animal();
console.log(anim.constructor===Animal); //anim由Animal构造出来,->true
console.log(Animal===Animal.prototype.constructor); //prototype对象的隐藏属性constructor反过来引用函数本身,->true
/**
* Animal = new Function()
* 因此Animal.constructor = Function,
* 而 Function = Function.prototype.constructor
* Animal.constructor = Function.prototype.constructor
*/
console.log(Animal.constructor===Function.prototype.constructor); // ->true
console.log(Function.prototype.constructor===Function); //true
3、深入理解Function、Object
JavaScript中有几个迷惑的地方:
1)Function、Object是函数;
2)new Function仍然是函数,new Object却是对象;
3)new (new Function) 又是对象;
var o2 =new Object();
var f3 = new Function('str','console.log(str)');
console.log('typeof Object:'+typeof Object); //function
console.log('typeof Function:'+typeof Function); //function
console.log('typeof o2:'+typeof o2); //object
console.log('typeof f3:'+typeof f3); //function
console.log('typeof new f3:'+typeof new f3()); //object
Function.prototype = function,是一个特例
console.log(typeof Function.prototype); //这是一个特例, ->function
console.log(typeof Function.__proto__); //function
console.log(typeof Function.__proto__ == Function.prototype) ->true
console.log(typeof Function.prototype.prototype); //undefined, 正常来说Function.prototype = function, function.prototype = object
console.log(typeof Function.prototype.__proto__); //object,这个要记住,后面会详细解释
console.log(typeof Object.prototype); //object, 好理解,Object是一个function
console.log(typeof Object.__proto__); //function, 好理解, Object = new Function,Object.__proto__ = Function.prototype
console.log(Object.prototype.prototype); //undefied, 好理解, Object.prototype = object(只有function才有prototype,所以prototype=undefiend)
console.log(Object.prototype.__proto__===null); //null, 必须记住,原型链结束
console.log(Function.prototype===Object.__proto__); //true,上面代码已经解释
console.log(Function.__proto__===Object.__proto__); //true, 因为Function.prototype = Function.__proto__
console.log(Function.prototype.__proto__===Object.prototype); //true,有点不明白?
Function.prototype. __ proto __=Object.prototype解释
console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true
根据instanceof原理,我们可以得出结论:
- Object.prototype(object)在Function的原型链上有;
Function . __ proto __ = function, != Object.prototype
因此只有Function . __ proto__ . __ proto __ = Object.prototype,
由于Function . __ proto__ = Function.prototype, 因此:
Function.prototype. __ proto __=Object.prototype - Function.prototype在Object的原型链上有;