构造函数
- 构造函数一般函数名大写
- 通过new关键字调用
- 箭头函数不可以做为构造函数
看个例子:
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function() {
alert(this.name)
}
}
var person1 = new Person('Zaxlct', 28, 'Engineer')
var person2 = new Person('Mick', 23, 'Doctor')
构造函数内部原理
1.在函数体最前面隐式加上
this = {
__proto__:Preson.prototype (隐式属性__proto__,它指的是构造函数构造出对象的原型)
}
2.执行this.xx = xx
3.隐式的返回this
prototype
每一个函数都有一个属性叫prototype(原型),它其实指向的是一个对象,这个对象有两个隐式属性constructor和__proto__,我们称这个对象叫原型对象,它的好处是用于扩展属性和方法。
看个例子:
Preson.prototype.name = 'wang'
function Preson() {
}
let Preson1 = new Preson()
let Preson2 = new Preson()
console.log(Preson1.name) // wang
console.log(Preson2.name) // wang
constructor
每个原型都有一个隐式属性construetor,它指向的是该实例对象的构造函数
Preson.prototype.constructor = function Preson() {}
proto
每一个js对象(除null)都有一个隐式属性叫__proto__,它指向的是该对象的原型
Preson.prototype.__proto__ = Object
Preson.prototype.__proto__ == Object.prototype
原型链
当查找实例对象的属性或方法时,如果对象本身没有,会向该对象原型查找,如果原型还没有,就向原型的原型查找,直到原型顶端,如果原型顶端还没有就返回undefined,它们之间是通过__proto__进行连接。
看个例子
Preson.prototype.name = 'wang'
function Preson() {
}
let preson = new Preson()
preson.name = 'zhang'
console.log(preson.name) // zhang
delete preson.name
console.log(preson.name) // wang
不是所有的对象最终都继承于Object.prototype,列如 Object.create(null)
继承
通俗的讲就是儿子能使用父辈的东西(东西指的是属性和方法)
原型链实现继承
原理;prototype的所有属性和方法可供该实例对象使用
function Parent() {
this.name = 'Loner'
this.sayHi = function() {
console.log('hello' + this.name)
}
}
let parent = new Parent()
function Child() {
}
Child.prototype = parent
let child = new Child()
child.sayHi() // helloLoner
parent.sayHi() // helloLoner
call和apll实现继承
原理:通过改变this指向实现继承,call和aplly区别在于传递的参数不一样,call是一个一个的传,apply第二个参数必须是一个数组
function Parent(name) {
this.name = name
this.sayHi = function() {
console.log('hello' + this.name)
}
}
function Child(name) {
Parent.call(this,name)
this.hi = function () {
console.log('hello' + this.name)
}
}
let child = new Child('老王')
child.sayHi() // heiio 老王
child.hi() // heiio 老王
圣杯模式实现继承
原理:核心点就是利用一个中间层做转换
var inherit = (function () {
var F = function() {};
return function(Target,Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
// 可用于查看最终继承于谁
Target.prototype._suber = Origin.prototype;
}
}())
Father.prototype.lastName = 'Loner'
function Father() {
}
function Son() {
}
inherit(Son,Father)
let son = new Son();
let father = new Father();
console.log(son)
extends关键字实现继承
注意: 子类的constructor方法没有调用super之前,就使用this关键字会报错。原因是:子类Children的构造函数之中的super(),代表调用父类Parent的构造函数。
super虽然代表了父类Parent的构造函数,但是返回的是子类Children的实例,即super内部的this指的是Children,因此super()在这里相当于Parent.prototype.constructor.call(this);
class Parent {
constructor(name,age) {
this.name = name;
this.age = age
}
sayHi() {
console.log(this.name)
}
}
class children extends Parent {
constructor(num) {
// super() 相当于Parent.prototype.constructor.call(this)
super('Loner','20') //super必须在前,否则代码报错
this.num = num
}
hi() {
console.log(this.num)
}
}
let c = new children(4)
c.hi() // 4
c.sayHi() // Loner
console.log(c.age) // 20