前端JS面试题-基础-原型和原型链
写在前面:本文内容主要根据慕课网双越老师的付费课程“一天时间迅速准备前端面试 快速构建初级前端知识体系 ”进行编写,主要是为了自己在面试前总结学习,欢迎留言指教。
本系列包括如下内容:
每一部分包括题目和知识点两部分。
原型和原型链
题目
- 如何准确判断一个变量是不是数组
- 手写一个建议的jQuery,考虑插件和扩展性
- class的原型本质,如何理解
1. 如何准确判断一个变量是不是数组
instanceof
2. 手写一个建议的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 = selector
//类似于数组,其实是一个对象
}
get(index) {
return this[index]
}
each(fn) {
for (let i = 0; i < this.length; i++) {
const element = this[i];
fn(element)
}
}
on(type, fn) {
return this.each(element => {
element.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) {
}
}
- html 内容
- 使用
3. class的原型本质,如何理解
- 原型和原型链的图示
- 属性和方法的执行规则
详见知识点3
知识点
1. class和继承
class的使用
- constructor
- 属性
- 方法
如下代码进行举例说明:
class Student {
// constructor
constructor(name, number) {
this.name = name //属性
this.number = number //属性
}
// 方法
sayHi() {
console.log(
// ``替代'',可以使用${}
`姓名 ${this.name}, 学号 ${this.number}`
)
}
}
继承的使用
- 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)
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}`)
}
}
2. 类型判断
instanceof
const a = ['Honda', 'Accord', 1998]
const b = '123'
console.log(a instanceof Array) //true
console.log(b instanceof Array) //false
3. 原型和原型链
首先,我们先分析一下在“继承的使用”中创建的class的类型
// class 实际上是函数,可见是语法糖
typeof People // 'function'
typeof Student // 'function'
语法糖的解释
在了解了class其实是函数后,我们再了解一下隐式原型和显示原型
// 隐式原型和显示原型
console.log(xialuo.__proto__) //xialuo是Student的实例
console.log(Student.prototype)
console.log(xialuo.__proto__ === Student.prototype)
查看打印结果:
因此我们可以得到原型关系:
- 每个class都有显式原型 prototype
- 每个实例都有隐式原型__proto__
- 实例的__proto__指向对应class的 prototype
可以得到下图:
基于原型的执行规则:
- 获取属性xialuo.name或执行方法xialuo.sayHI()时
- 先在自身属性和方法寻找
- 如果找不到则自动去__proto__寻找
接着,我们再次打印
console.log(Student.prototype.__proto__)
console.log(People.prototype) //People是Student的父类
console.log(Student.prototype.__proto__ === People.prototype)
因此我们可以得到如下的原型关系:
- 子类的prototype的__proto__指向其父类的prototype
可以得到下图:
之后,我们再进一步
console.log(People.prototype.__proto__)
console.log(Object.prototype)
console.log(People.prototype.__proto__ === Object.prototype)
打印结果如下:
可以得到下图: