## 理解javascript 原型
MDN[继承与原型链](https://developer.mozilla.org/zh-CN/docs/JavaScript/Guide/Inheritance_and_the_prototype_chain)
这篇文章大致讲解了JavaScript原型的相关知识,但是你可能还是迷惑的,不是吗?
## 迷惑点1 我们常说的原型是指啥
好,你是一位很会问问题的人,上面的文章也说了,我们通常所说的原型或者基于原型的继承
更多的是说[[prototype]],而这个prototype不是我们常见的那个来自于函数(或构造函数)
的内部属性值,[[prototype]] 在很多浏览器的实现里面就是`__proto__`,晕了吧,怎么又蹦出来
一个`__proto__`?
## 迷惑点2 `__proto__`和obj.prototype的关系是啥
首先你要明白的是:
1、在js中一切都是对象,对象是由类(js中是构造函数)造出来的
2、对象是拥有`__proto__`属性的,但没有prototype
3、类没有`__proto__`属性,但有prototype;
4、由同一个类实例化(new)得到的对象的`__proto__`是引用该类的prototype
## 迷惑点3 constructor 是啥
在Javascript语言中,constructor属性是专门为function而设计的,它存在于每一个function的prototype属性中。这个constructor保存了指向function的一个引用。
在我们创建一个函数的时候JavaScript内部会执行如下几个动作:
1. 为该函数添加一个原形属性(即prototype对象).
2. 为prototype对象额外添加一个constructor属性,并且该属性保存指向函数F的一个引用。
这样当我们把函数F作为自定义构造函数来创建对象的时候,对象实例内部
会自动保存一个指向其构造函数(这里就是我们的自定义构造函数F)的prototype对象的一个属性__proto__,所以我们在每一个对象实例中就可以访问构造函数的prototype
所有拥有的全部属性和方法,就好像它们是实例自己的一样。
当然该实例也有一个constructor属性了(从prototype那里获得的),这时候constructor的作用就很明显了,因为在这时,每一个对象实例都可以通过constrcutor对象访问它的构造函数。
例子
以下的代码,可能你已经看到或用过上百次了,但这里又把它搬上来了,但可能会有些新意。
代码如下//构造器. this 作为新对象返回并且它内部的[[prototype]]属性将被设置为构造器默认的prototype属性
var Circle = function(radius) {
this.radius = radius;
//next line is implicit, added for illustration only
//this.__proto__ = Circle.prototype;
} www.111cn.net
//扩充 Circle默认的prototype对象的属性因此扩充了每个由它新建实例的prototype对象的属性
Circle.prototype.area = function() {
return Math.PI*this.radius*this.radius;
}
//创建Circle的两个示例,每个都会使用相同的prototype属性
var a = new Circle(3), b = new Circle(4);
a.area().toFixed(2); //28.27
b.area().toFixed(2); //50.27
这很棒。如果我改变了constructor的prototype属性,即使是已存在的实例对象也可以立刻访问新的prototype版本吗?
嗯......不完全是。如果我修改的是现存prototype的属性后,那么确实是这种情况,因为对象创建时a.__proto__引用了A.prototype所定义的对象。
代码如下var A = function(name) {
this.name = name;
}
var a = new A("alpha");
a.name; //"alpha"
A.prototype.x = 23;
a.x; //23
big军
翻译于 1年前
0人顶
顶 翻译的不错哦!
但是如果我将prototype属性用一个新对象代替,a.__proto__ 仍然指向原始对象。
代码如下var A = function(name) {
this.name = name;
}
var a = new A("alpha");
a.name; //"alpha"
A.prototype = {x:23};
a.x; //null一个缺省的prototype是什么样的?
一个拥有constructor属性的对象。
代码如下var A = function() {};
A.prototype.constructor == A; //true
var a = new A();
a.constructor == A; //true (a 的constructor属性继承自它的原型)
Cloud_Lee
翻译于 1年前
0人顶
顶 翻译的不错哦!
其它翻译版本(1)
正在加载...
instanceof与prototype有啥关系?
如果A的prototype属性出现在a的原型链中,则表达式a instanceof A会返回true。这意味着我们可以欺骗instanceof,让它失效。
var A = function() {}
var a = new A();
a.__proto__ == A.prototype; //true - so instanceof A will return true
a instanceof A; //true;
//mess around with a"s prototype
a.__proto__ = Function.prototype;
//a"s prototype no longer in same prototype chain as A"s prototype property
a instanceof A; //false
原型链
了解了new运算符以及原型的作用之后,一起来看看什么是[[Prototype]]?以及对象如何沿着这个引用来进行属性的查找?
在js的世界里,每个对象默认都有一个[[Prototype]]属性,其保存着的地址就构成了对象的原型链,它是由js编译器在对象 被创建 的时候自动添加的,其取值由new运算符的右侧参数决定:当我们var object1 = {};的时候,object1的[[Prototype]]就指向Object构造函数的原型对象,因为var object1 = {};实质上等于var object = new Object();(原因可参照上述对new A的分析过程)。
对象在查找某个属性的时候,会首先遍历自身的属性,如果没有则会继续查找[[Prototype]]引用的对象,如果再没有则继续查找[[Prototype]].[[Prototype]]引用的对象,依次类推,直到[[Prototype]].….[[Prototype]]为undefined(Object的[[Prototype]]就是undefined)
代码如下//我们想要获取a1.fGetName
alert(a1.fGetName);//输出undefined
//1、遍历a1对象本身
//结果a1对象本身没有fGetName属性
//2、找到a1的[[Prototype]],也就是其对应的对象A.prototype,同时进行遍历
//结果A.prototype也没有这个属性
//3、找到A.prototype对象的[[Prototype]],指向其对应的对象Object.prototype
//结果Object.prototype也没有fGetName
//4、试图寻找Object.prototype的[[Prototype]]属性,结果返回undefined,这就是a1.fGetName的值
简单说就是通过对象的[[Prototype]]保存对另一个对象的引用,通过这个引用往上进行属性的查找,这就是原型链。
[深入理解jvm虚拟机 第三版 pdf]深入理解JavaScript的原型
http://m.bbyears.com/wangyezhizuo/50247.html
推荐访问: