面下对象一些概念
JS中实现继承的方式主要是通过原型链的方法
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针
什么是构造函数? 通过new关键字来实例化的函数就叫构造函数 构造函数有prototype(显示原型)属性以及__proto__(隐式原型)显示原型,隐式原型
每个函数function都有一个prototype,即显式原型(属性)
每个实例对象都有一个__proto__,可称为隐式原型(属性)
对象的隐式原型的值为其对应构造函数的显式原型的值
什么是原型? 每个构造函数都有一个原型对象, 都包含指向原型对象内部的指针
// Function 与 Object 原型链关系
console.log(Function.prototype.__proto__ == Object.prototype) // true
console.log(Object.prototype.__proto__) // null
// 声明的函数
function fun1(){}
console.log(fun1.prototype.__proto__ == Object.prototype) // true
console.log(fun1.prototype.__proto__ == Function.prototype.__proto__) // true
var o1 = new fun1()
function fun2(){}
fun2.prototype = o1
console.log(fun2.prototype != fun1.prototype) //true
var o2 = new fun2()
console.log(o2.__proto__ == fun2.prototype) // true
// 创建一个对象、空对象 的隐式原型指向 Object的原型
var obj = new Object() // 等效 var obj = {}
console.log(obj.__proto__ == Object.prototype) // true
类式继承
ES5
// 声明父类
function superClass(){
this.suerValue = true
}
superClass.prototype.getsuperVal = function(){
return this.suerValue;
}
// 声明子类
function sonClass(){
this.subVaue = false;
}
//继承父类
sonClass.prototype = new superClass();
//为子类添加共有方法
sonClass.prototype.getsupVal = function(){
return this.subVaue;
}
var instance = new sonClass();
console.log(instance.getsuperVal()); // true
console.log(instance.getsupVal()); // false
- 在ES5之前 js 中得继承是通过prototype 属性来继承父类得方法
- 也可以通过 改变this 指向来继承
ES6
// 声明父类
class superClass{
constructor() {
this.suerValue = true
}
getsuperVal(){
return this.suerValue;
}
}
// 声明子类 并且继承父类 ES6 继承新写法 继承关键字为 extends
class sonClass extends superClass{
constructor() {
//继承后一定要使用 super
super()
this.subVaue = false;
}
getsupVal(){
return this.subVaue;
}
}
var instance = new sonClass();
console.log(instance.getsuperVal()); //true
console.log(instance.getsupVal()); //false
类不能直接访问这些属性必须要通过prototype 原型来访问,当我们实例化父类得 superClass
创建新的对象复制了构造函数内部得属性方法,并且将原型上面得
__proto__指向了父类得原型对象,这样就拥有得父类得原型对象(属性和方法), 并且这个新的对象可以直接访问父类得原型对象, 我们继承这个对象不仅仅可以访问父类得属性方法还可以,访问父类构造函数得属性方法,
- 使用 instanceof 属性判断某个对象是否是某个类得实例,或者是否继承了某个类
- instanceof 是通过prototrp 来确定某个类是否是某个类得实例
console.log(instance instanceof sonClass); //true
console.log(instance instanceof superClass); //true
// 子类 instanceof 父类
console.log(sonClass instanceof superClass); // false
构造函数继承
缺点 会把子类的原型的方法全部干掉 当让也可避免这个问题 就是在原型上面新添加一个对象来解决
//父类
function sperClass(val){
this.suerValue = val;
this.books = ['123','456']
}
sperClass.prototype.getVal = function(){
console.log(this.books);
}
// 声明子类
function sonClass(name){
sperClass.call(this,name)
}
let sip = new sonClass('JavaScript');
sip.books.push('uni-app')
console.log(sip.books); //["123", "456", "uni-app"]
console.log(sip.suerValue); // JavaScript
console.log(sip.getVal()); //sip.getVal is not a function
构造函数总结
- 构造函数主要继承实现是通过 call()函数来实现 来改变要继承函数得this指向 call 放法会立即执行函数所以调用子类得时候已经包父类得this指向改变了所以我们在调用子类得时候能够调用和使用父类得方法。
- 这种继承没有设计到原型(prototype) 所以子类是没有办法使用父类原型上面得属性和方法得,所以父类得原型方法调用是会报错
组合继承 也称有点继承
//父类
function superClass(){
this.suerValue = true
}
superClass.prototype.getsuperVal = function(){
return this.suerValue;
}
// 声明子类
function sonClass(){
this.subVaue = false;
}
sonClass.prototype.getsupVal = function(){
return this.subVaue;
}
// 原型继承父类
// 这里把子类的 getsupVal全部干掉了,只剩下父类的东西可用 子类原型的方法不可用
sonClass.prototype = new superClass()
var instance = new sonClass();
console.log(instance.getsuperVal()); // true
console.log(instance.getsupVal()); // instance.getsupVal is not a function 前面继承把这个方法干掉了
//解决办法
sonClass.prototype.fu = new superClass()
var instance1 = new sonClass();
console.log(instance1.fu.getsuperVal());//true
console.log(instance1.getsupVal()); // false