function Person(){}
const person = new Person()//实例化
person.name = 'liu'

Person是一个构造函数,用new实例化创建了一个实例对象person

Prototype

  • 每个函数都有一个prototype属性
  • prototype是函数才会有的属性(看谷歌浏览器下的控制台)
  • 函数的prototype指向了一个对象,这个对象是调用该构造函数而创建的实例的原型,如下的person1,person2的原型
function Person(){}
const person1 = new Person()//实例化
const person2 = new Person()//实例化

原型:每一个js对象(除null外)在创建的时候都会与之关联另一个对象,这个对象也就是我们所说的原型,每一个对象都会从原型继承属性

构造函数与实例原型的关系

__proto__

这是每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。 (谷歌跟火狐添加的,该属性不稳定,建议用getPrototypeOf)

person.__proto__ === Person.prototype; // true
实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?

constructor

  • 没有指向实例的,因为一格构造函数可以生成多个实例
  • 但是有指向构造函数的,即constructor
  • 每个原型都有一个constructor属性指向关联的构造函数
Person === Person.prototype.constructor // true

实例与原型

当读取实例的属性时,如果找不到,则会查找与对象相关联的原型的属性,如果还查不到,就去查原型的原型,直到找到最顶层为止,返回undefined

function Person() {}
Person.prototype.name = 'liu';

var person = new Person();

person.name = 'chen';
console.log(person.name) // liu

delete person.name;//从 person 对象中找不到 name 属性就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找
console.log(person.name) // chen

原型的原型

原型对象是通过Object构造函数生成的,实例的__proto__指向构造函数的prototype

原型链

蓝色线为原型链

注:

1)首先是constructor属性

function Person() {}
var person = new Person();
console.log(person.constructor === Person); // true

当获取person.constructor时,其实实例constructor并没有constructor属性,但是会从person的原型也就是Person.prototype中读取,所以有

person.constructor === Person.prototype.constructor

2)其次是__proto__

绝大部分的浏览器都支持这个非标准方法访问原型,但是它并不存在于Person.prototype中,它实际上来自于Object.prototype,当使用obj.__propo__时可以理解为返回了Object.getPrototypeOf(obj)

3)关于继承

最后是关于继承,前面我们讲到“每一个对象都会从原型‘继承’属性”,实际上,继承是一个十分具有迷惑性的说法,引用《你不知道的JavaScript》中的话,就是:

继承意味着复制操作,然而 JavaScript 默认并不会复制对象的属性,相反,JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。


爬。