大家先看看这之前这篇文章,牢记一些概念。
链接: 构造函数,原型,实例的关系,原型链是什么.
// 1.原型链继承
// 先看个小栗子
function F(){
}
let s = new F()
Object.prototype.x = 1
console.log(s.x) // 1 通过原型链获得的x值
s.x = 2
console.log(s.x) // 2 自己的x值
/*
// 以上是原型搜索机制,当以读取模式访问一个实例属性时,
// 先再实例搜索这个属性,如果没有会继续搜索原型
// 通过原型链实现的继承的情况下,搜索过程就可以一直沿着原型链继续找,
// 直到末端Object(原型链末端)的默认原型
*/
function Father(){
this.v = 1
this.arr = [6,6,6]
}
Father.prototype.func1 = function(){
console.log('father')
}
function Son(){
this.v = 2
}
// 继承
Son.prototype = new Father()
// Son.prototype 是Father的实例,所以获得了father的所有属性
// 创建儿子实例
let obj = new Son()
obj.func1() // father
// 方法重写,本质上是一个在自己身上的方法,不是通过原型链使用的父方法
// 另外注意,重写要在继承之后,因为原型的指向会发生改变
Son.prototype.func1 = function(){
console.log('Son')
}
obj.func1() //Son
let obj2 = new Son()
obj2.arr.push(9)
console.log(obj.arr) //[6, 6, 6, 9]
console.log(obj2.arr) //[6, 6, 6, 9]
/*
// 可以看出优点是可以简单实现继承
// 缺点是引用类型数据,会被不同实例影响
*/
可以先看看这篇文章再理解下面的内容
链接: js简单理解call(),apply(),bind()和this.
// 2.借用构造函数
function F(x){
this.arr = [1,1,1]
this.x = x
}
function S(){
// 继承
F.call(this,'b')
this.age = 1
}
let z = new S()
console.log(z) //[1, 1, 1]
let c = new S()
c.arr.push(2)
console.log(c) //[1, 1, 1, 2]
/*
// new 的方式调用构造函数实际上会经历以下4个步骤
// 1创建一个新对象
// 2将构造函数的作用域给新对象(使用call或者apply,所以this就指向了这个新对象)
// 3执行构造函数中的代码(为这个新对象添加属性)
// 4返回这新对象 给接收的实例变量
用变量z做例子
// 首先创建了一个新对象 假设是o
// 在o的环境中调用构造函数,所以构造函数里面的this都是指向的这个o对象
// 然后把里面的属性都给这个o
// 返回o的地址给变量z接收
*/
/*
// 优点可以不影响其他原型的情况下传递参数给上级构造函数,
// 并且解决了引用类型数据的问题
// 缺点是方法如果都定义在构造函数中的话,函数也就无法复用了,
// 指的是每次都会在实例上//挂载一个新的function;
// 理解成没有挂载在原型上的方法就行了
*/
// 3.组合继承 (经典继承)
function F(x){
this.x = x
this.arr = [1,1,1]
}
F.prototype.func = function(){
console.log(this.x)
}
function S(x,y){
// 继承属性
F.call(this,x)
this.y = y
}
// 继承方法
S.prototype = new F()
S.prototype.func1 = function(){
console.log(this.y)
}
let o1 = new S('o1',11)
o1.arr.push(2)
console.log(o1.arr) //[1, 1, 1, 2]
o1.func() // o1
o1.func1() // 11
let o2 = new S('o2',22)
console.log(o2.arr) // [1,1,1]
o2.func() // o2
o2.func1() // 22
/*
// 没有明显的缺点,主要是在继承属性和方法时都调用了一次父类,即执行了两次父类方法。
// 是使用比较多的继承方式,
// 另外还有原型式继承,寄生式继承,寄生组合式继承,有余力的同学可以了解一下
// 优点是解决了上面两个的缺点
*/