构造函数
- 存在于es6的class语法之前,面向对象的一种表示方法。
- 提取一类相似属性方法的对象整合成一个函数,用new关键字执行这类函数
实例
- 用new关键字声明的对象称之为实例
- 实例化的对象具备构造函数的实例属性,其内部this指向为此实例对象
原型
- 所有实例对象的公共祖先称为原型对象,由
prototype表示;区别于实例中的原型属性,由内置的__proto__属性表示 - 原型对象和原型属性两者指向相同,但构造函数声明的原型对象具备实际意义,可赋值改变;而实例中的原型属性只是为了让实例可以访问调用原型上的方法所做的映射,并不具备语义化
- 获取原型对象的方式:
- 构造函数访问直接用
[consFun].prototype语法取得 - 实例访问不建议使用内置
__proto__属性,此属性没有语义化,暴露出来容易破坏原型对象的值或结构;因此采用es6的Object.getPrototypeOf()方法获取实例对应原型
- 构造函数访问直接用
__proto__
构造器
- 存在于每个构造函数本身的内置属性
- 指向为当前实例对象
- 需要注意构造函数的constructor是存在于其默认的
prototype上,因此构造函数定义在prototype上的属性方法用.属性名来赋值避免覆盖原始的prototype
原型对象的继承
- 原型链继承
//父 function Father() { this.a = { money: 100, birth:1996 }; this.b = [1,2,3]; } //子 function Son() {} Son.prototype = new Father(); //共享同一个prototype;存在引用值共享问题 let son = new Son(); let son1 = new Son(); son.a.birth = 1990; son.b.push(4); console.log(son.a,son1.a); //{money: 100, birth: 1990} {money: 100, birth: 1990} console.log(son.b,son1.b); //(4) [1, 2, 3, 4] (4) [1, 2, 3, 4] //此原型链 // son -> Son.prototype(new Father) -> Father.prototype - 解决原型对象继承中引用值共享问题:
//构造函数继承 //父 function Father() { this.a = { money: 100, birth:1996 }; } Father.prototype = { log() { console.log(`father's log`); }, constructor: Father //此处手动保证构造器始终是Father,目的是使得实例对象指向更清晰 } //子 function Son() { Father.call(this); } //1.先实例化父原型,当下方子实例化再次call的时候会把绑定this更改,实际上Father调用了2次,此方式无法让子构造函数定义自己的原型, Son.prototype = new Father(); //2.利用es5的深拷贝方式让父构造函数的原型直接成为子构造函数的原型一部分,子改变会改变父 Son.prototype = Object.create(Father.prototype); //3.利用中间构造函数 function Mid(){}; Mid.prototype = Father.prototype; Son.prototype = new Mid(); Son.prototype.constructor = Son;