Zer0e's Blog

浅谈JavaScript中的原型链

字数统计: 1.1k阅读时长: 4 min
2018/11/02 Share

前言

Javascript是我最喜欢的几种语言之一,从暑假后半段一直到开学一直在看《Javascript高级程序设计》,我觉得这本书很好,讲得很全面,但对于js中的原型链自己还是有必要花点时间好好理一理,于是就写下此篇文章。

基础知识

先来讲讲js中创建对象的几种方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//第一种:字面量
var o1 = {name:'o1'}
var o2 = new Object({name:'o2'})
//第二种:使用构造函数
var F = function(name){this.name = name;}
var o3 = new F('o3');
//第三种:使用Object.create
var o = {name:'o4'}
var o4 = Object.create(o)

console.log(o1);
console.log(o2);
console.log(o3);
console.log(o4);

让我们看看结果:

3种创建方法返回的结果是不一样的。这就和这篇文章要讲的有关系。

原型&&原型链

先上两张《js高级程序设计》中关于原型链的图片

这两张图对于萌新甚至是某些老手都没理解清楚。
我自己做了一张流程图,下面我们就来细说图中的名词。

让我们从实例出发:

1
2
var F = function(name){this.name = name;}
var o3 = new F('o3');
  • 所谓的实例就是生成出来的对象,例如上面的例子中o3就是实例
  • F就是构造函数,用来提供创建对象的方法
  • 实例中的__proto__指向原型对象
  • 实例的构造函数的prototype也是指向的原型对象
  • 原型对象的construor指向的是构造函数
我们用console来看看 ![](https://zer0blog.oss-cn-hangzhou.aliyuncs.com/blog_image/js-prototype/05.png)基本上就和流程图上的差不多。

那什么是原型链呢?
简单地说,就是由原型所组成的链,一个对象的__proto__就是它的原型,而这个原型也是一个对象,所以他也有__proto__属性,指向它的上一个原型,一直通过__proto__向上查找,直到Object的时候,这条原型链就到头了。

说了这么多,原型链到底有啥用?
当我们通过构造函数创建了许多实例,如果某些对象要增加方法,一个个去实例中添加就很繁琐,这时我们可以将方法添加到原型中,使这个原型的所有实例都有这个方法。举个代码例子:

1
2
3
4
5
6
7
8
9
var F = function(name){this.name = name;}
var o3 = new F('o3');
var o5 = new F('o5');
o3.__proto__.say=function(){
console.log('hello JavaScript')
};

o3.say()
o5.say()
![](https://zer0blog.oss-cn-hangzhou.aliyuncs.com/blog_image/js-prototype/06.png)我们可以发现打印出了相同字符串。

原型链的另一个作用就是继承,再举个简单的小例子:

1
2
3
4
5
6
7
var Father = function(name){this.name = name;};
Father.prototype.say=function(){console.log("hello world!")};
var a = new Father("javascript");
function Son(){};
Son.prototype = a;
var b = new Son()
b.say();
![](https://zer0blog.oss-cn-hangzhou.aliyuncs.com/blog_image/js-prototype/07.png)

这里可以很清楚,b中并没有say这个方法,而是从father那边继承过来的,我们可以看看Son.prototype
可以看到原型链一直到Object。

回到最初创建对象的方法。
第一种就直接使用Object类来创建实例,所以__proto__直接指向了Object;第二种方法使用了构造函数,可以看到o3的__proto__指向了__函数构造出来的对象(原型对象)__,而这个对象的__proto__s指向的是Object;最后第三种方法使用了Object.create。MDN的文档中给出:Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
所以o4._proto__指向的是它的父对象(允许我这么叫它),而o4._proto.__proto__指向的才是Object。
这也就是为什么三种方式在console里面返回的结果不同。至于使用构造函数创建的o3在console里为什么会这么显示,让人觉得o3.__proto__指向Object就不得而知了。

总结

对于js,原型链一直是它的难点和重点,这次通过简单的复习和梳理再次学习了一下。
写下这篇文章也算是对JavaScript的一种喜爱和敬畏吧,对于原型链也只是了解了皮毛,希望今后对js的学习可以更加深入。
如有错误或者讲的不当的地方请与我联系。

参考

《JavaScript高级程序设计》
https://www.cnblogs.com/chengzp/p/prototype.html

CATALOG
  1. 1. 前言
  2. 2. 基础知识
  3. 3. 原型&&原型链
  4. 4. 总结
  5. 5. 参考