Js中Prototype、__proto__、Constructor、Object、Function关系介绍
2017-03-14 00:42
766 查看
Function、Object、Prototype、__proto__内存关系图
上面的内存图跟堆栈结构可以参照文章Javascript_01_理解内存分配。
堆区图说明:
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
prototype、constructor内存关系图(在Function、Object、Prototype关系图上加入constructor元素):
上图中,红色箭头表示函数对象的原型的constructor所指向的对象。
注意Object.constructor===Function;本身Object就是Function函数构造出来的
如何查找一个对象的constructor,就是在该对象的原型链上寻找碰到的第一个constructor属性所指向的对象。
参考:
http://www.cnblogs.com/fool/category/264215.html (javascript原理介绍)
http://www.libuchao.com/2012/05/14/prototypes-in-javascript/ (JavaScript 的原型对象 Prototype)
http://rockyuse.iteye.com/blog/1426510 (理解js中的原型链,prototype与__proto__的关系)
我们接着看代码:
[javascript] view
plain copy
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
var one=new Person('js');
one.showMe();//js,这个结果没有什么好奇怪的
one.from();//I come from prototype.,这个结果有一点奇怪吧
要解释这个结果就要仔细研究一下new这个操作符了.var one=new Person('js');这个语句执行的过程可以分成下面的语句:
[javascript] view
plain copy
var one={};
Person.call(one,'js');
按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:
第一步是建立一个新对象(叫A吧);
第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;
第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。
其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了。
又头晕了,上图吧!inobj就是__proto__ 即,one.__proto__ == Person.prototype
这样one对象通过内置的原型对象inobj就可以直接访问Person的prototype对象中的任何属性与方法了。这也就解释了上面的代码中为什么one可以访问form函数了。因为prototype对象中有一个constructor属性,那么one也可以直接访问constructor属性。
代码:
[javascript] view
plain copy
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
var one=new Person('js');
one.showMe();//js,这个结果没有什么好奇怪的
one.from();//I come from prototype.,这个结果有一点奇怪吧
alert(one.constructor);//function Person(name) {...}
alert(Person.prototype.constructor);//function Person(name) {...}
接着看继承是如何实现的。
[javascript] view
plain copy
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
function SubPerson()
{
}
SubPerson.prototype=new Person();
var subOne=new SubPerson();
subOne.from();//I come from prototype.
alert(subOne.constructor);//function Person(name) {...};
alert(SubPerson.prototype.constructor);//function Person(name) {...};
继承的实现很简单,只需要把子类的prototype设置为父类的一个对象即可。注意这里说的可是对象哦!
那么通过prototype属性实现继承的原理是什么呢?还是先看图形说明,然后编写代码进行验证。
用图像直观表示如下:
图 1.3
到此说明了a,b两点是正确的。
同事上面的也可以论证一下观点(该观点摘自JavaScript权威指南):
1) 同一个类的所有实例都从同一个原型对象上继承属性
2) 当且仅当两个对象继承自同一个原型对象时,他们才是属于同一个类的实例
特别说明:只有构造函数才有prototype属性,而构造函数的实例是没有该属性的,也就是说console.log(a1.prototype)输出的是undefined。在javascript中,每个函数都自动有一个prototype属性,而不是每一个对象拥有prototype属性
原型属性与实例对象的创建与否没有关系,它在对象创建之前就已经存在
直观表示如下图:
图 1.5
注意:新定义Prototype对象的话,该Prototype对象原有的constructor属性会丢失,该Prototype此时所指的对象(即{getName:function(){return this.name}}对象)的constructor就是Object,事实上{getName:function()}就是一个Object对象。相信如果A.prototype={getName:function(){returnthis.name}}换成这样写的话,理解起来会方便写:
Var obj = {getName:function(){}}
A.prototype = obj;
//或者这样写:
Var obj = new Object();
Obj.getName = function(){
};
A.prototype = obj;
此时用图形表示a1,a2,prototype对象的关系如下:
通过这个图可以很直观的看出:
a1.constructor === A//=>false
a1.constructor === Object//=>true
A.prototype.constructor === Object
.修改这个问题的办法就行给重定义的Prototype对象显式的添加一个constructor属性,修改其constructor的指向:
A { name: 'aa2', show: [Function] }
{ [Function: A] shows: [Function], alarms: [Function] }
{ [Function: A] shows: [Function], alarms: [Function] }
[Function: Function]
A { show1: [Function] }
A { show1: [Function] }
[Function: Function]
undefined
static-A static show
static-A static show
static-A static show
inner-aa1 inner show
sdfsdfs
inner dynamic alarm
true
true
A { show1: [Function] }
prototype show
上面的内存图跟堆栈结构可以参照文章Javascript_01_理解内存分配。
堆区图说明:
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
prototype、constructor内存关系图(在Function、Object、Prototype关系图上加入constructor元素):
上图中,红色箭头表示函数对象的原型的constructor所指向的对象。
注意Object.constructor===Function;本身Object就是Function函数构造出来的
如何查找一个对象的constructor,就是在该对象的原型链上寻找碰到的第一个constructor属性所指向的对象。
参考:
http://www.cnblogs.com/fool/category/264215.html (javascript原理介绍)
http://www.libuchao.com/2012/05/14/prototypes-in-javascript/ (JavaScript 的原型对象 Prototype)
http://rockyuse.iteye.com/blog/1426510 (理解js中的原型链,prototype与__proto__的关系)
我们接着看代码:
[javascript] view
plain copy
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
var one=new Person('js');
one.showMe();//js,这个结果没有什么好奇怪的
one.from();//I come from prototype.,这个结果有一点奇怪吧
要解释这个结果就要仔细研究一下new这个操作符了.var one=new Person('js');这个语句执行的过程可以分成下面的语句:
[javascript] view
plain copy
var one={};
Person.call(one,'js');
按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:
第一步是建立一个新对象(叫A吧);
第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;
第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。
其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了。
又头晕了,上图吧!inobj就是__proto__ 即,one.__proto__ == Person.prototype
这样one对象通过内置的原型对象inobj就可以直接访问Person的prototype对象中的任何属性与方法了。这也就解释了上面的代码中为什么one可以访问form函数了。因为prototype对象中有一个constructor属性,那么one也可以直接访问constructor属性。
代码:
[javascript] view
plain copy
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
var one=new Person('js');
one.showMe();//js,这个结果没有什么好奇怪的
one.from();//I come from prototype.,这个结果有一点奇怪吧
alert(one.constructor);//function Person(name) {...}
alert(Person.prototype.constructor);//function Person(name) {...}
接着看继承是如何实现的。
[javascript] view
plain copy
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
function SubPerson()
{
}
SubPerson.prototype=new Person();
var subOne=new SubPerson();
subOne.from();//I come from prototype.
alert(subOne.constructor);//function Person(name) {...};
alert(SubPerson.prototype.constructor);//function Person(name) {...};
继承的实现很简单,只需要把子类的prototype设置为父类的一个对象即可。注意这里说的可是对象哦!
那么通过prototype属性实现继承的原理是什么呢?还是先看图形说明,然后编写代码进行验证。
用图像直观表示如下:
图 1.3
到此说明了a,b两点是正确的。
同事上面的也可以论证一下观点(该观点摘自JavaScript权威指南):
1) 同一个类的所有实例都从同一个原型对象上继承属性
2) 当且仅当两个对象继承自同一个原型对象时,他们才是属于同一个类的实例
特别说明:只有构造函数才有prototype属性,而构造函数的实例是没有该属性的,也就是说console.log(a1.prototype)输出的是undefined。在javascript中,每个函数都自动有一个prototype属性,而不是每一个对象拥有prototype属性
原型属性与实例对象的创建与否没有关系,它在对象创建之前就已经存在
直观表示如下图:
图 1.5
注意:新定义Prototype对象的话,该Prototype对象原有的constructor属性会丢失,该Prototype此时所指的对象(即{getName:function(){return this.name}}对象)的constructor就是Object,事实上{getName:function()}就是一个Object对象。相信如果A.prototype={getName:function(){returnthis.name}}换成这样写的话,理解起来会方便写:
Var obj = {getName:function(){}}
A.prototype = obj;
//或者这样写:
Var obj = new Object();
Obj.getName = function(){
};
A.prototype = obj;
此时用图形表示a1,a2,prototype对象的关系如下:
通过这个图可以很直观的看出:
a1.constructor === A//=>false
a1.constructor === Object//=>true
A.prototype.constructor === Object
.修改这个问题的办法就行给重定义的Prototype对象显式的添加一个constructor属性,修改其constructor的指向:
/** * Created by duqiong on 17/3/13. */ function A(name){ this.name = name; this.show=function () {//只是实例方法,不实例化无法调用 console.log('inner-'+this.name+' inner show'); // A.show(); } } A.shows=function () { console.log('static-'+this.name+' static show'); } var a2 = new A("aa2"); A.prototype.show1=function () {//只是在A的原型对象(实例)增加实例方法,不需要实例化不能调用 console.log('prototype show'); } A.alarms=function () { console.log('sdfsdfs'); this.alarm=function () {//只是修改了类方法,类方法不需要实例化 console.log('inner dynamic alarm'); } //this.alarm(); } var a1 = new A("aa1"); // console.log(a1); console.log(a2); console.log(a1.constructor); console.log(a2.constructor); console.log(a2.constructor.constructor); console.log(A.prototype); console.log(a1.__proto__); console.log(A.constructor); console.log(a1.prototype); // A.shows(); a1.__proto__.constructor.shows();//通过实例调用类静态方法 a1.constructor.shows();//通过实例调用类静态方法 a1.show(); A.alarms();
A.alarms();console.log(a1.__proto__===A.prototype);console.log(a1.constructor===A);console.log(A.prototype);a1.show1();
////print//////
A { name: 'aa2', show: [Function] }
{ [Function: A] shows: [Function], alarms: [Function] }
{ [Function: A] shows: [Function], alarms: [Function] }
[Function: Function]
A { show1: [Function] }
A { show1: [Function] }
[Function: Function]
undefined
static-A static show
static-A static show
static-A static show
inner-aa1 inner show
sdfsdfs
inner dynamic alarm
true
true
A { show1: [Function] }
prototype show
相关文章推荐
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍总结
- !!Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- <转载>Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- 【转】Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍总结
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍 ,JS原型
- Prototype、__proto__与Object、Function关系介绍
- js中Object.__proto__===Function.prototype
- Js prototype constructor __proto__ Function Object 关系图
- JS 一张图理解prototype、proto和constructor的关系
- 理清javascript中prototype、__proto__、Object、Function的关系,更好地理解原型继承
- js的prototype、proto和constructor的关系