在JavaScript中原型和原型链是很抽象的概念,对于大多数人也是最难理解的一部分,掌握原型和原型链的本质是JavaScript进阶的重要一环。分享一下我对JavaScript原型和原型链的理解。
一、 函数对象
JavaScript 中,万物皆对象。但对象也是有区别的,分为:普通对象和函数对象,Object 、Function 是 JS 自带的函数对象。
var myNewObject1 = {};//myNewObject1为普通对象
var myNewObject2 = new Object();//myNewObject2为普通对象
var myNewObject3 = new fun1();//myNewObject3为普通对象
function fun1(){};//fun1为函数对象
var fun2 = function(){};//fun2为函数对象
var fun3 = Function('str','console.log(str)');//fun3为函数对象
console.log(typeof Object);//function
console.log(typeof Function)//function
console.log(typeof fun1);//function
console.log(typeof fun2);//function
console.log(typeof fun3);//function
console.log(typeof myNewObject1);//object
console.log(typeof myNewObject2);//object
console.log(typeof myNewObject3);//object
二、prototype
和__proto__
的区别
2.1 prototype
定义:函数才有的属性
2.2 __proto__
定义:每个对象都有的属性,但__proto__
不是一个规范属性,只是部分浏览器实现了此属性,对应的标准属性[[Prototype]]
注:大多数情况下__proto__
可以理解为“构造器的原型”
__proto__ === constructor.prototype
(如果一个对象是通过Object.create函数构造出来的,.那其proto就不一定是.constructor.prototype了)
var m = {};
console.log(m.prototype); //undefined
console.log(m.__proto__); //Object {}
var n = function(){}
console.log(n.prototype); //n {}
console.log(n.__proto__); //function() {}
三、 原型和原型链
3.1 原型
一个对象,其他对象可以通过它实现属性继。
3.2 原型链
__proto__
是任何对象都有的属性,所以会形成一条__proto__
连接起来的链条,递归访问__proto__
必须最终到头,并且值为NULL。
自己是由自己创建的,好像不是很符合逻辑。但仔细想想,现实世界也类似的情形,正如《道德经》里所说“无,名天地之始”。
当js引擎查找对象的属性时,先查找对象本身是否存在该属性,如果不存在,会在原型链上查找,而不会查找自身的prototype
var M = function(){};
var m = new M();
console.log(m.__proto__); //M {}(即构造器function M 的原型对象)
console.log(m.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象)
console.log(m.__proto__.__proto__.__proto__); //null
总结
每个对象都有 proto 属性,但只有函数对象才有 prototype 属性