一 Prototype、__proto__与Object、Function关系介绍
Function、Object:Js自带的函数对象。
Function、Object:Js自带的函数对象。
prototype:显示原型。每一个函数对象都有一个显示的prototype属性,它代表了对象的原型(Function.prototype函数对象是个例外,没有prototype属性)。
__proto__:隐式原型。
每个对象都有一个名为__proto__的内部隐藏属性,指向于它所对应的原型对象
(chrome、firefox中名称为__proto__,并且可以被访问到)。
原型链正是基于__proto__才得以形成(注:不是基于函数对象的属性prototype)。
下面举个例子:
<script type="text/javascript">
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
var p = new Person();
p.Say();
</script>
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
var p = new Person();
p.Say();
</script>
这段代码很简单,相信每个人都这样写过,那就让我们看下为什么p可以访问Person的Say。
首先var p=new Person();可以得出p.__proto__=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性, 于是,他就需要到他的__proto__中去找,也就是Person.prototype,而我们在上面定义了 Person.prototype.Say=function(){}; 于是,就找到了这个方法。
再看:
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
Person.prototype.Salary = 50000;
var Programmer = function () { };
Programmer.prototype = new Person();
Programmer.prototype.WriteCode = function () {
alert("programmer writes code");
};
var p = new Programmer();
p.Say(); //Person say
p.WriteCode();//programmer writes code
alert(p.Salary);//50000
Person.prototype.Say = function () {
alert("Person say");
}
Person.prototype.Salary = 50000;
var Programmer = function () { };
Programmer.prototype = new Person();
Programmer.prototype.WriteCode = function () {
alert("programmer writes code");
};
var p = new Programmer();
p.Say(); //Person say
p.WriteCode();//programmer writes code
alert(p.Salary);//50000
二:Js中每个对象(null除外)都和另一个对象相关联,通过以下例子跟内存效果图来分析Function、Object、Prototype、__proto__对象间的关系。
function Animal(){
}
var anim = new Animal();
console.log('***********Animal anim proto*****************');
console.log(' typeof Animal.prototype:' + typeof Animal.prototype); // object
console.log('anim.__proto__===Animal.prototype:'+(anim.__proto__===Animal.prototype)); // true
console.log('Animal.__proto__===Function.prototype:'+(Animal.__proto__===Function.prototype)); // true
console.log('Animal.prototype.__proto__===Object.prototype:'+(Animal.prototype.__proto__===Object.prototype)); // true
console.log('***********Function proto*****************');
console.log(' typeof Function.prototype:'+ typeof Function.prototype); // function
console.log(' typeof Function.__proto__:'+ typeof Function.__proto__); // function
console.log(' typeof Function.prototype.prototype:'+ typeof Function.prototype.prototype); // undefined
console.log(' typeof Function.prototype.__proto__:'+ typeof Function.prototype.__proto__); // object
console.log('Function.prototype===Function.__proto__:'+(Function.prototype===Function.__proto__)); // true
console.log('***********Object proto*****************');
console.log(' typeof Object.prototype:'+ typeof Object.prototype); // object
console.log(' typeof Object.__proto__:'+ typeof Object.__proto__); // function
console.log('Object.prototype.prototype:'+Object.prototype.prototype); // undefied
console.log('Object.prototype.__proto__=== null:'+(Object.prototype.__proto__=== null)); // null
console.log('***********Function Object proto关系*****************');
console.log('Function.prototype===Object.__proto__:'+(Function.prototype===Object.__proto__)); // true
console.log('Function.__proto__===Object.__proto__:'+(Function.__proto__===Object.__proto__)); // true
console.log('Function.prototype.__proto__===Object.prototype:'+(Function.prototype.__proto__===Object.prototype)); // true
/* ******************** 系统定义的对象Array、Date *************************** */
console.log('**************test Array、Date****************');
var array = new Array();
var date = new Date();
console.log('array.__proto__===Array.prototype:'+(array.__proto__===Array.prototype)); // true
console.log('Array.__proto__===Function.prototype:'+(Array.__proto__===Function.prototype)); // true
console.log('date.__proto__===Date.prototype:'+(date.__proto__===Date.prototype)); // true
console.log('Date.__proto__===Function.prototype:'+(Date.__proto__===Function.prototype)); // true
Function、Object、Prototype、__proto__内存关系图
堆区图说明:
Function.prototype函数对象图内部表示prototype属性的 红色虚框 ,只是为了说明这个属性不存在。
通过上图Function、Object、Prototype关系图中,可以得出一下几点:
- 所有对象所有对象,包括函数对象的原型链最终都指向了Object.prototype,而Object.prototype.__proto__===null,原型链至此结束。
- Animal.prototype是一个普通对象。
- Object是一个函数对象,也是Function构造的,Object.prototype是一个普通对象。
- Object.prototype.__type__指向null。
- Function.prototype是一个函数对象,前面说函数对象都有一个显示的prototype属性,但是Function.prototype却没有prototype属性,即Function.prototype.prototype===undefined,所有Function.prototype函数对象是一个特例,没有prototype属性。
- Object虽是Function构造的一个函数对象,但是Object.prototype没有指向Function.prototype,即Object.prototype!==Function.prototype。
三: Prototype跟Constructor关系介绍
在 JavaScript 中,每个函数对象都有名为“prototype”的属性
(上面提到过Function.prototype函数对象是个例外,没有prototype属性)
,用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身。这是一种循环引用(i.e.
Animal.prototype.constructor===Animal)。
通过以下例子跟内存效果图来分析Prototype、constructor
间的关系。
console.log('**************constructor****************');
console.log('anim.constructor===Animal:'+(anim.constructor===Animal)) ; // true
console.log('Animal===Animal.prototype.constructor:'+(Animal===Animal.prototype.constructor)) ; // true
console.log('Animal.constructor===Function.prototype.constructor:'+(Animal.constructor===Function.prototype.constructor)); // true
console.log('Function.prototype.constructor===Function:'+(Function.prototype.constructor===Function)); // true
console.log('Function.constructor===Function.prototype.constructor:'+(Function.constructor===Function.prototype.constructor)); // true
console.log('Object.prototype.constructor===Object:'+(Object.prototype.constructor===Object)); // true
console.log('Object.constructor====Function:'+(Object.constructor===Function)); // true
console.log('anim.constructor===Animal:'+(anim.constructor===Animal)) ; // true
console.log('Animal===Animal.prototype.constructor:'+(Animal===Animal.prototype.constructor)) ; // true
console.log('Animal.constructor===Function.prototype.constructor:'+(Animal.constructor===Function.prototype.constructor)); // true
console.log('Function.prototype.constructor===Function:'+(Function.prototype.constructor===Function)); // true
console.log('Function.constructor===Function.prototype.constructor:'+(Function.constructor===Function.prototype.constructor)); // true
console.log('Object.prototype.constructor===Object:'+(Object.prototype.constructor===Object)); // true
console.log('Object.constructor====Function:'+(Object.constructor===Function)); // true
prototype、constructor内存关系图(在Function、Object、Prototype关系图上加入constructor元素):
附:一个例子