[深入理解jvm虚拟机 第三版 pdf]深入理解JavaScript的原型

时间:2019-05-09  来源:网页配色  阅读:

## 理解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

推荐访问:
相关阅读 猜你喜欢
本类排行 本类最新