1. 什么是原型?什么是原型链?
js是面向对象的,每个实例对象都有一个_proto_
属性指向它的原型对象,该实例的构造函数有一个原型属性prototype
,与实例的_proto_
属性指向同一个对象,同时,原型对象的constructor
指向构造函数本身。
原型:每一个 JavaScript
对象(null
除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型
原型链:
当一个对象在查找一个属性时,自身没有就会根据_proto_
属性向它的原型进行查找,如果还是没有,则向它的原型的原型继续查找,直到查找到Object.prototype._proto_
也就是null
,这样就形成了原型链。
2. 如何准确判断一个变量是不是数组?
使用 instanceof 去判断即可
a instanceof Array
3. class 的原型本质, 怎么理解?
- 原型和原型链的图示
- 属性和方法的执行规则
下面就是相关知识点
知识点:
-
class 和 继承
-
类型判断 instanceof
-
原型和原型链
(一)
class (基本使用)
// 类
class Student {
constructor(name, number) {
this.name = name
this.number = number
// this.gender = 'male'
}
sayHi() {
console.log(
`姓名 ${this.name}, 学号 ${this.number}`
)
}
}
// 通过类 new 对象/实例
const xiaolu = new Student('夏洛', 100)
console.log(xiaolu.name)
console.log(xiaolu.name)
xiaolu.sayHi()
const madongmei = new Student('马冬梅', 101)
console.log(madongmei.name)
console.log(madongmei.number)
madongmei.sayHi()
继承
- extends (继承)
- super (传递参数给父类)
- 扩展或重写方法
// 父类
class People {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name} eat something`)
}
}
// 子类
class Student extends People {
constructor(name, number) {
super(name) // super 的作用, 是把 name 这个参数传递给 Pepole 这个 父类 中
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)
console.log(xialuo.number)
xialuo.sayHi()
xialuo.eat()
// 实例
const wanglaoshi = new Teacher('王老师', '语文')
console.log(wanglaoshi.name)
console.log(wanglaoshi.major)
wanglaoshi.teach()
wanglaoshi.eat()
(二)
类型判断 - instanceof
// 判断 xiaoluo 由哪个父类构建出来的
// 前面的变量 是否由 后面变量 构建出来的
// 后面变量 是 前面的变量的一个父类
xiaolu instanceof Student // true xiaolu 是 Student 构建 (new) 出来的
xiaolu instanceof People // true People 是 xiaolu 的父类
xiaolu instanceof Object // true Object 是否所有对象的父类
[] instanceof Array // true
[] instanceof Object // true
{} instanceof Object // true
原型
// class 实际上是函数, 可见是语法糖
typeof People // ’function‘
typeof Student // ’function‘
// 隐式原型 和 显示原型
console.log( xiaoluo.__proto__ ) // 隐式原型
console.log( xiaoluo.prototype ) // 显示原型
conosle.log( xiaoluo.__proto__ === xiaoluo.prototype ) // true
原型关系图 (Student 是 class, xiaoluo 是实例)
原型关系
- 每个 class 都有显示原型
prototype
- 每个实例都有隐式原型
__proto__
- 实例的
_proto_
指向对应 class 的prototype
(隐式原型 指向 显示原型)
基于原型的执行规则
- 获取属性
xiaolu.name
或执行方法xiaolu.sayhi()
时 - 先在自身属性和方法寻找
- 如果找不到则自动去
__proto__
中查找
原型链
// Student 继承于 People
console.log( Student.prototype.__proto__ )
console.log( People.prototype )
console.log( People.prototype === Student.prototype.__proto__ )
xiaoluo -> Student -> People -> Object
instanceof 原理
instanceof 通过隐私原型 一层一层的向上寻找 父类的显示原型, 找到了就返回 true
【重要提示 !!! 】
class 是 ES6 语法规范, 由 ECMA 委员会发布
ECMA 只规定语法规则, 即我们代码的书写规范
以上实现方式都是 V8 引擎的实现方式, 也是主流的
4. new Object() 和 Object.create() 的区别
区别
- {} 等同于 new Object(), 原型 Object.prototype
- Object.create(null) 没有原型
- Object.cteate({…}) 可指定原型
原理
Object.create 创建一个空对象, 然后把空对象原型指向到传入的对像的隐式原型上
const obj3 = Object.create(null)
const obj4 = new Object() // {}
const obj5 = Object.create({
a: 10,
b: 20,
sum() {
return this.a + this.b
}
})
5. 如何用 JS 实现继承?
各种方式
- class 继承
- prototype 继承