JavaScript 原型、原型链的深入理解

在 JavaScript 中,大部分东西都是对象,数组是对象,函数也是对象,对象更加是对象。不管我们给数组和函数定义什么内容,它们总是有一些相同的方法和属性。比如说hasOwnProperty(),toString()等。

这说明一个对象所拥有的属性不仅仅是它本身拥有的属性,它还会从其他对象中继承一些属性。当 JavaScript 在一个对象中找不到需要的属性时,它会到这个对象的父对象上去找,以此类推,这就构成了对象的原型链。理解js的原型链对使用 JavaScript 的对象非常有帮助。

让我们通过一个例子由浅到深地理解原型链:

function Foo(_name) {
  this.name = _name;
}
Foo.prototype.show = function() {
  console.log('I am ', this.name);
};
var f1 = new Foo('obj1');
var f2 = new Foo('obj2');

f1.show();  //  I am obj1
f2.show();  //  I am obj2

这是我们经常使用的创建对象的方式,将共同的方法放到 Foo.prototype 中,所有实例都共有这个方法了。
这是怎么实现的呢?我们看下面这张图:

我们先只用看第一行

我们定义的show函数在Foo.prototype中,当我们执行f1.show()时,JavaScript 发现f1本身没有show这个属性,所以它就到f1的原型(也就是__proto__指向的对象)去找,找到了就可以调用。

注:每个对象都有一个方法 hasOwnProperty() 来检查对象本身是否有某个属性,如果有则返回 true ;如果这个属性在它的原型链上或原型链上都没有,则返回 false ;

图片第一行告诉了我们4点:

  • 所有函数都有一个prototype指针,指向原型对象,如图中的Fooprototype指针。prototype指针的意义是,当我们使用这个构造函数new出新对象的时候,新对象的原型是谁。
  • 构造函数的prototype所指向的原型对象有一个constructor指针,指回构造函数。如图中Foo.prototypeconstructor指针指向Fooconstructor指针有助于我们找到一个对象的构造函数是谁。
  • __proto__每个对象都有,JavaScript 在new一个对象的时候,会将它的__proto__指向构造函数的prototype指向的那个对象。在上图中,f1f2这些实例对象的__proto__都指向了Foo.prototype
  • 如果一个对象的__proto__指向了另一个对象,那么前者就继承了后者的所有属性。

注:__proto__ 与 prototype 的区别!__proto__ 才是真正连接原型链的东西,而 prototype 只是构造函数的一个指针属性而已。

图片后面展示了 JavaScript 原生对象的继承关系

先看Foo的原型。Foo是一个函数,它的构造函数是 JavaScript 内部的function Function()Functionprototype指向了一个对象Function.prototype,因此Foo__proto__就指向了Function.prototype

注:所有的函数都以 function Function() 为构造函数,因此,所有函数(包括 function Function() 和 function Object() )的 __proto__ 都指向 Function.prototype 这个对象,这个对象中定义了所有函数都共有的方法,比如 call() 、 apply() 等。

Function.prototype这个对象,是一个普通的对象,它的构造函数是 JavaScript 内置的function Object()function Object()prototype指向Object.prototype,因此Function.prototype.__proto__就指向Object.prototype,这个对象中定义了所有对象共有的属性,比如我们之前说的hasOwnProperty()toString()

注:同理,Foo.prototype 和其他自定义的对象也是 __proto__ 指向 Object.prototype 对象,就不需要说明了。

Object.prototype就是原型链的终点了,它的__proto__null,JavaScript 查找属性时,如果到这里还没有找到,那就是undefined了。

注:到这里就不难理解为什么我们说在 JavaScript 中,函数也是对象了,它就是继承自对象的。

转载:https://www.jianshu.com/p/116ea3be6ef5

posted @ 2021-06-16 14:14  lqqgis  阅读(71)  评论(0编辑  收藏  举报