1.class
constructor
属性
方法
// 类
class Student {
// 构造函数
constructor(name, number) { // 属性
this.name = name
this.number = number
}
// 方法
sayHi() {
console.log(`姓名 ${this.name} 学号 ${this.number}`)
}
}
// 实例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name, xialuo.number)
xialuo.sayHi()
// 实例
const madongmei = new Student('马冬梅', 101)
console.log(madongmei.name, madongmei.number)
madongmei.sayHi()
// ---------------------
// 夏洛 100
// 姓名 夏洛 学号 100
// 马冬梅 101
// 姓名 马冬梅 学号 101
2.继承
extends
super
// 父类
class People {
constructor(name) {
this.name = name
}
eat(something) {
console.log(`${this.name} eat ${something}`)
}
}
// 子类
class Student extends People {
constructor(name, number) {
super(name)
this.number = number
}
sayHi() {
console.log(`学生 ${this.name} 学号 ${this.number} 打招呼~`)
}
}
// 子类
class Teacher extends People {
constructor(name, major) {
super(name)
this.major = major
}
teach() {
console.log(`${this.name} 教授 ${this.major}`)
}
}
// 实例:学生
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name, xialuo.number)
xialuo.sayHi()
xialuo.eat('蛋糕')
// 实例:老师
const wanglaoshi = new Teacher('王老师', '语文')
console.log(wanglaoshi.name, wanglaoshi.major)
wanglaoshi.teach()
wanglaoshi.eat('茄子')
// ---------------------
// 夏洛 100
// 学生 夏洛 学号 100 打招呼~
// 夏洛 eat 蛋糕
// 王老师 语文
// 王老师 教授 语文
// 王老师 eat 茄子
3.类型判断-instanceof
instanceof 可以判断引用类型
Object 是所有类 class 的父类
Student 继承于 People , People 继承于 Object
console.log(xialuo instanceof Student)
console.log(xialuo instanceof People)
console.log(xialuo instanceof Object)
console.log([] instanceof Array)
console.log([] instanceof Object)
console.log({}
instanceof Object)
4.原型
4.1 class 实际上是函数,可见是语法糖
console.log(typeof Student)
console.log(typeof People)
// 解释:
// js的 class 继承不像 java 纯继承,而是原型继承
// class 本质还是一个 function
console.log(typeof Object)
console.log(typeof Array)
4.2 隐式原型和显示原型
console.log(xialuo.__proto__)
console.log(Student.prototype)
console.log(xialuo.__proto__ === Student.prototype) // true
xialuo.name
"夏洛"
xialuo.number
100
xialuo.sayHi()
学生 夏洛 学号 100 打招呼~
undefined
xialuo.__proto__
People {constructor: ƒ, sayHi: ƒ}
xialuo.__proto__.sayHi()
学生 undefined 学号 undefined 打招呼~
undefined
xialuo.__proto__.name
undefined
xialuo.__proto__.number
undefined
xialuo.__proto__ === Student.prototype
true
5.原型图
6.原型关系
每个 class 都有显示原型 prototype
每个实例都有隐式原型 __proto__
实例的 __proto__ 指向对应 class 的 prototype
7.基于原型的执行规则
获取属性 xialuo.name 或执行方法 xialuo.sayHi() 时
先在自身属性和方法寻找
如果找不到则自动去 __proto__ 中查找
8.原型链
console.log(People.prototype === Student.prototype.__proto__)
9.原型链图
10.向上找
class 里调用属性调用方法的本质,以及继承的本质包括如何继承于 Object 的本质。
11.instanceof
顺着隐式原型向上找,对应到 class 的显示原型。
12.JS原型本章相关的面试题
题目解答
• 如何准确判断一个变量是不是数组?
console.log(a instanceof Array)
• class的原型本质,怎么理解?
答:
原型和原型链的图示(不参考任何自己画下来)
属性和方法的执行规则(如何通过链向上找,也很重要)
• 手写一个简易的jQuery,考虑插件和扩展性
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
this[i] = result[i]
}
this.length = length
this.selector
}
get(index) {
return this[index]
}
each(fn) {
for (let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
}
on(type, fn) {
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
}
// 扩展很多 DOM API
}
// 插件
jQuery.prototype.dialog = function(info) {
alert(info)
}
// 覆写“造轮子”
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
}
style(data) {
}
}