对于JavaScript中原型链的理解

时间:2022-02-25 19:00:25

先理解两条概念

  • JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做_ proto _的原型属性,用于指向创建它的 对象 的 原型对象prototype。

  • 原型对象prototype也是一个对象,因此它也有_ proto _ 属性。

图片

  • 自己画了一张图,画的比较抽象可能看不懂,下面我会根据图示一点点的来谈谈自己的理解。

对于JavaScript中原型链的理解

1. JS内置对象是Function对象的一个实例。

我们熟知的js的内置对象有:

  • String
  • Date
  • Array
  • Math
  • RegExp
  • Number
  • Object
  • Null
  • Boolean
  • 当然也包括Function

    如果了解构造函数和构造函数原型的应该知道,每一个函数都会有一个prototype原型对象。当我们实例化这个函数以后,实例化的对象也会有一个_ proto _ 内置属性。此时这个对象的_ proto _ 属性指向的是构造函数的prototype对象。因此这个对象就可以调用构造函数的prototype中的属性和方法。

举个栗子

// 构造函数Person
function Person(name,age) {
this.name = name;
this.age = age;
}

// 实例化一个对象xx
var xx = new Person();
console.log(xx.__proto__ === Person.prototype); // true

// xx是一个对象,而Person是一个函数,我们还可以理解为对象是由函数实例化出来的,因此:
console.log(Object.__proto__ == Function.prototype); //true
  • 不光Object,所有内置对象都是Function对象的实例对象,所以他们的_ proto _ 都与Function.prototype相等,也包括Function本身。
<script>
console.log(Number.__proto__ === Function.prototype) // true
console.log(Boolean.__proto__ === Function.prototype) // true
console.log(String.__proto__ === Function.prototype) // true
console.log(Object.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
console.log(Array.__proto__ === Function.prototype) // true
console.log(RegExp.__proto__ === Function.prototype) // true
console.log(Error.__proto__ === Function.prototype) // true
console.log(Date.__proto__ === Function.prototype) // true
</script>
  • 按照上面图片所示的,xx是函数Person一个实例对象,所以xx._ proto _ 指向的就是Person.prototype,即xx._ proto _ === Person.prototype
  • 函数本身也是一个对象,所以也包含_ proto _ 属性。同时函数还可以是构造者,包含prototype原型对象。因此:Function._ proto _ === Function.prototype。
  • 因为Function._ proto _ === Function.prototype。所以我们可以理解为构造函数Person._ proto _ === Function.prototype。
<script>
function Person(name,age) {
this.name = name;
this.age = age;
}

var xx = new Person();

console.log(xx.__proto__ === Person.prototype); // true

console.log(Object.__proto__ == Function.prototype); // true

console.log(Person.__proto__ == Function.prototype); //true
// 返回的都是true
</script>

2. 内置对象实例的原型指向

  • 我们创建一个对象,例如var obj = {}或者是var obj = new Object。都可以看成是实例化了 Object这个内置对象。换而言之,就是内置对象Object构造了obj这个实例对象。
  • 现在引出一句很绕口的话:内置对象的实例对象的原型 指向 构造这个实例对象的内置对象的原型。其实理解起来很简单,obj(实例对象)是由Object( 内置对象 )构造的,那么obj._ proto _ === Object.prototype。
<script>
var obj = {name: 'jack'}
var arr = [1,2,3]
var reg = /hello/g
var date = new Date
var err = new Error('exception')

console.log(obj.__proto__ === Object.prototype) // true
console.log(arr.__proto__ === Array.prototype) // true
console.log(reg.__proto__ === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype) // true
console.log(err.__proto__ === Error.prototype) // true
</script>

3.内置对象的原型对象的原型指向(Object除外)

  • 又是一个很绕口的标题。

  • 内置对象的原型对象,例如:Array.prototype。

  • 内置对象的原型对象的原型就是:Array.prototype._ proto _

  • 如图片所示,是用内置对象Function做了一个栗子,Function.prototype._ proto _ 指向的是 Object.prototype。即:Function.prototype._ proto _ === Object.prototype。

  • 如图片所示,构造函数Person的原型对象。即Person.prototype 对象也有_ proto _ 属性,它也指向Object的prototype。即:Person.prototype__ proto __ === Object.prototype

  • 其余的内置对象也同理。

console.log(Array.prototype.__proto__ === Object.prototype); 
//true
// 其余内置对象同理

注意 : Object.prototype._ proto _ = null。

  • 内置对象Object.prototype也有_ proto _属性,其为null,并不等于Object.prototype。