Skip to content

原型和原型链

什么是原型,什么是原型链?

JS 有一个重要的概念,万物皆对象。 每一个实例对象都有一个私有属性(proto)指向他的原型对象,这就是原型。 此原型对象也有一个自己的原型对象,这样一层一层直到某一个的对象的原型对象为 null。这就构成原型链。

了解原型链主要关注

  • prototype , proto , constructor 3 个属性对象
  • 普通对象、函数对象、实例对象

栗子

javascript
var obj = {}
var obj1 = new Object()

var fun1 = function () {}
function Fun2() {}
var fun3 = new Fun2()

console.log(obj)
console.log(obj1)

console.dir(fun1)
console.dir(Fun2)
console.dir(fun3)
可见每一个对象都有一个属性 proto
每一个对象都有一个proto, 其不是一个标准属性([[Prototype]]); 其可以认为是 构造器的原型 proto === constructor.prototype

什么是普通对象,什么是函数对象

普通对象是通过函数对象创建的,函数对象又是通过 new Function 创建的

  • 凡是通过 new Function 创建的都是函数对象(可以通过 new 去创建一个普通对象) fun1 Fun2 是函数对象 Object,String,Boolean,Function,Array,Date,RegExp.. 都是函数对象
  • 其他的都是普通对象(都是通过 new(函数对象) 去创造的) obj obj1 fun3 都是普通对象

prototype , proto , constructor

1. constructor

所有的对象都存在一个 constructor 其指向 其构造函数

js
var obj = {}
var obj1 = new Object()

var fun1 = function () {}
function Fun2() {}
var fun3 = new Fun2()

// 普通对象
console.log(obj.constructor === Object)
console.log(obj1.constructor === Object)

// 函数对象
console.log(fun1.constructor === Function)
console.log(Fun2.constructor === Function)
// 普通对象
console.log(fun3.constructor === Fun2)

2. prototype, proto

每一个对象都有一个proto,每一个函数对象都有一个 prototype 属性 即 我们每定义一个对象的时候(函数对象也是对象)都会预置一些属性,其中就有一个 proto 属性 因为函数对象也是对象 所以我们定义的对象是函数对象的时候 其还会添加一个 prototype 属性,指向其原型。

js
var obj = {}
var obj1 = new Object()

var fun1 = function () {}
function Fun2() {}
var fun3 = new Fun2()

console.log(obj.__proto__) // { constructor : Object() , hasOwnProperty , isPrototypeOf, toString() , valueOf()}
console.log(obj1.__proto__) // { constructor : Object() , hasOwnProperty , isPrototypeOf, toString() , valueOf()}

console.log(fun3.__proto__) // { constructor : Fun2() , __proto__ : }

console.dir(Fun2.__proto__) // { constructor : Function() , __proto__: {}, apply,arguments...  }
console.dir(Fun2.prototype) // { constructor : Fun2() , __proto__ : }
console.dir(fun1.__proto__) // { constructor : Function() , __proto__: {}, apply,arguments...  }
console.dir(fun1.prototype) // { constructor : f() , __proto__ : }
那什么是 prototype 其就是函数对象的原型对象?
javascript
function Person() {}
console.dir(Person.prototype) // {constructor: Person() , __proto__ :}
// 可见我们创建一个函数对象的时候 其会默认创建一个 prototype原型对象属性(就是一个普通对象),因为是对象所有有__proto__ 属性,然后再设置了一个constructor属性  指向其构造函数

console.log(Person.prototype.constructor === Person) //true
// 函数对象肯定用来 去 新建一个 普通对象的
// 如
var zs = new Person("张三")
console.log(zs) // 这是一个普通对象 所以其包含一个 __proto__ : {constructor: Person(), __proto__ :} 发现其跟Person.prototype一样
console.log(zs.__proto__ === Person.prototype) //true
console.log(zs.__proto__.constructor === Person && Person.prototype.constructor === Person) //true

function Person(name, type) {
  this.name = name
  this.type = type
}
Person.prototype = {
  type: "人类",
  getName: function () {
    return this.name
  },
}
Person.prototype.constructor = Person
var zs = new Person("张三", "畜生")
var ls = new Person("李四", "禽兽")
console.log(zs) // {name: "张三", type: "畜生" , __proto__ : {type: "人类",getName : function(){},constructor : Person,__proto__ : {} }}
console.log(ls) // {name: "李四", type: "禽兽" , __proto__ : {type: "人类",getName : function(){},constructor : Person,__proto__ : {} }}
// 可见prototype对象  是我们通过函数对象创建一个实例对象的时候 定义了其公共的属性方法,然后再添加一个constrctor 那我们定义一个实例对象的时候就可以追本溯源,知道这货是怎么创建的。

// 原型链
// zs这一个实例对象 的 __proto__ 指向其创建函数的原型对象
console.log(zs.__proto__ === Person.prototype)
// 其创建函数的原型对象也是一个普通对象  肯定可有__proto__ 那么这个普通对象是谁创建的 Object  所以
console.log(Person.prototype.__proto__ === Object.prototype)
// 对象函数对象的原型的创建函数  想想肯定就是对象 那么就会无限循环下去了  所以 其对象的创建函数为 null
console.log(Object.prototype.__proto__ === null)

//Person这个函数对象  也是对象,所以肯定也有 __proto__ 那么是什么创造了函数对象那,应该就是  原生的Function
console.log(Person.__proto__ === Function.prototype)
console.log(function () {}.__proto__ === Function.prototype)
console.log(obj.__proto__ === Object.prototype)
console.log(true.__proto__ === Boolean.prototype)
console.log(new Number(10).__proto__ === Number.prototype)

// 原生的Function 也是一个对象 所以其创建函数也就是 对象
console.log(Function.prototype.__proto__ === Object.prototype)
// 那么可见
console.log(Array.prototype.__proto__ === Object.prototype)
console.log(String.prototype.__proto__ === Object.prototype)
console.log(Boolean.prototype.__proto__ === Object.prototype)
console.log(Date.prototype.__proto__ === Object.prototype)
javascript
zs:{
    __proto__ : Person.prototype : {
        constructor : Person,
        __proto__   : Object.prototype :{
            __proto__ : null
        }
    }
}
Person : {
    prototype: {
        constructor : Person,
        ... 用于自定义公共属性或者方法
    },
    __proto__ : Function.prototype : {
         __proto__   : Object.prototype :{
              __proto__ : null
         }
    }
}

JS 原型链简单图解参考 1