原型到底是什么

64 阅读2分钟

创建对象的几种方式

  1. 对象字面量
var Person = {
  name: 'tianzhen',
  say: function() {
    console.log(this.name)
  }
}
Person.say()
  1. new Object()
var Person = new Object()
Person.name = 'tianzhen'
Person.say = function() {
  console.log(this.name)
}
Person.say()

方法1和方法2都属于同一种方法,1是2的语法糖,可以看到,对象其实也是new出来的

  1. 使用原型
var Person = function() {}
Person.prototype.name = 'tianzhen'
Person.prototype.say = function() {
  console.log(this.name)
}
var p = new Person()
p.say()
var p2 = new Person()
p2.say()

p和p2都可以共享原型上的属性和方法

原型到底是什么?

上面出现了prototype,那么它是函数的原型吗?

理解原型

当一个JavaScript对象在创建的时候,就会与之关联另一个对象(创建这个对象的函数的prototype),这个对象就是我们所说的原型,每一个对象都会从原型上继承属性

当一个函数在创建之后,就会产生一个原型对象(prototype),当通过这个函数的构造函数创建了一个具体对象后,这个具体对象中有一个属性(proto)指向原型

我们使用如下代码来分析原型是什么

function Person() {}
const p = new Person()

new 函数我们通常称为是构造函数,它返回的是一个对象。 对象p的原型是什么?答案就是Person.prototype 那么Person的原型又是什么?

prototype

  1. 每一个函数都有一个prototype属性
  2. 它指向了一个对象
  3. 这个对象就是调用它的构造函数而创建的实例的原型

所以p的原型就是Person.prototype

__proto__

每一个对象(null除外)都有一个__proto__属性,又称隐式原型,规范中定义为[[prototype]],它指向该对象的原型

  1. 根据上面的描述得出
  • p有一个属性p.__proto__
  • p.__proto__指向p的原型即Person.prototype
  1. Person是个函数,它有没有__proto__?
  • Person是函数但也是对象,所以它也有__proto__
  • Person.__proto__ === ?
  1. 定义函数的另一种方式new Function
const Person = new Function()

看到这里大家应该就明白了上面Person的原型是什么了-- Person.__proto__ === Function.prototype

__proto__又是从哪里来的?

  • 来自Object.prototype
  • 因为所有的原型都继承了Object.prototype,所以可以访问__proto__
  • 访问p.__proto__ 可以理解为Object.getPrototypeOf(p)

总结

所以我们平时所说的原型其实就是对象的__proto__,对象构造函数的prototype