new原理
new的关键:执行一个构造函数 返回一个实例对象
内部执行步骤:
graph TD
创建一个新对象 --> 对象指向构造函数的原型-绑定this-this指向新对象 --> 执行构造函数 --> 返回新对象
手写 New
function create(fn,...args){
if(typeof fn !== 'function'){
throw 'fn not a function'
}
var obj = Object.create(fn.prototype)
var res = fn.apply(obj,args)
return res instanceof Object ? res : obj
}
1.obj继承了函数fn的原型 拥有了它身上的属性
2.改变函数的this指向 将this指向obj这个对象 这样obj就可以访问到fn构造函数上的属性
3.如果有返回值 则将其作为new操作返回的对象 否则返回obj
继承
- 不使用Object.create 组合继承(构造函数继承、原型链继承)
- 使用Object.create 寄生组合继承(原型式继承、寄生式继承)
1.构造函数继承
借助call
function Parent(){
this.name = 'parent'
}
function Child(){
Parent.call(this)
this.type = 'child'
}
但是这种方式无法继承父类的方法
2.原型链继承
function Parent(){
this.name = 'parent'
this.play = [1,2]
}
function Child(){
this.type = 'child'
}
Child.prototype = new Parent()
这种方式可以访问父类的属性和方法 但是当创建两个子类的实例时 改变其中一个 另一个也会被改变 因为他们共用的一个原型
3.上面两种组合继承
function Parent(){
this.name = 'parent'
this.play = [1,2]
}
function Child(){
Parent.call(this)
this.type = 'child'
}
Child.prototype = new Parent()
3.寄生组合继承:解决了组合继承中 子类继承父类的无用属性的问题
function Parent(){
this.name = 'parent'
this.play = [1,2]
}
function Child(){
Parent.call(this)
this.type = 'child'
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
ES6 Class继承 js中不存在类的概念 class只是语法糖🍬 其本质是函数
class Parent {
constuctor(value){
this.val = value
}
getValue(){
console.log(this.val)
}
}
class Child extends Parent{
constuctor(value){
super(value)
this.val = value
}
}
let child = new child(520)
child.getValue() //输出520