Appearance
es5 类与继承
// 父类
class Person {
construtor(name, age){
this.name = name
this.age = age
}
sayHello(){
console.log("父类")
}
}
// 子类,会继承父类的变量与方法;construtor 中必须传入父类有的变量,并执行 super
class Student extends Person {
construtor(name, age, sex){
super()
this.sex = sex
}
learn(){
console.log("子类")
}
}
const zhangsan = new Student('张三',16,'男')
zhangsan.sayHello() // 父类
zhangsan.learn() // 子类
继承
- 子类,会继承父类的变量与方法;
construtor
中必须传入父类有的变量,并执行super()
instanceof
判断两个对象是否在同一条原型链上
zhangsan instanceof Student // true
zhangsan instanceof Person // true
zhangsan instanceof Object // true
zhangsan instanceof Array // false
原型
把上面的类例子改成原始的写法,可以参考上一个学习篇章大师课中实战栏目的内容
function Student(name,age){
this.name = name
this.age = age
}
Student.prototype.learn = function(){
console.log("子类")
}
const zhangsan = new Student('张三',18)
console.log(zhangsan)
- 打印
zhangsan 对象
:
- 打印
zhangsan.__proto__
- 打印
Student.prototype
zhangsan.__proto__
与 Student.prototype
的打印是一样的,为什么呢?
我们在一个类或者 function 下定义方法就是使用
Student.prototype.learn
的形式创建实例,即 new 的时候到底做了什么
- 首先创建一个新的空对象
- 然后将空对象的
__proto__
指向构造函数的原型即 :obj.__proto__ = Student.prototype
- 将 this 指向这个空对象并执行构造函数,apply
- 构造函数有返回值则返回返回值,否则返回这个空对象
// 代码实现 function myNew(Con, ...args) { // 创建一个新的空对象 let obj = {}; // 将这个空对象的__proto__指向构造函数的原型,即 obj.__proto__ = Con.prototype; Object.setPrototypeOf(obj, Con.prototype); // 将this指向空对象 let res = Con.apply(obj, args); // 对构造函数返回值做判断,然后返回对应的值 return res instanceof Object ? res : obj; }
为什么
obj.__proto__ = Student.prototype
,因为 new 做了这件事情,并且我们在 类/function 中定义中就是这样去声明一个方法的
仔细看前面的打印
Function 是所有函数的构造函数,图解: