「面试梳理-JS」原型和原型链

140 阅读2分钟

谈谈你原型链的理解?

函数与对象的关系?

原型的类别?

原型的概念?

原型链的概念?

关于Function和Object?

原型、构造函数、实例、原型链?

instanceof?

继承?

1. 函数与对象的关系?

  • javascript 中,一切皆是对象
  • 函数是对象,对象是通过函数创建的

2. 原型的类别?

  • 显示原型: prototype, 每个函数function独有的属性
  • 隐示原型: _ _ proto _ _,每个对象都具有的属性

3. 原型的概念?

  • 所有的实例对象都有一个属性_ _ proto _ _
  • 所有的构造函数都有一个属性prototype
  • 所有实例对象的_ _ proto _ _ 指向它构造函数的prototype

原型和原型链.jpg

4. 原型链的概念?

  • 概念: 当访问某个对象的属性时,先在该对象本身属性上找,找不到,则会去其隐式原型_ _ proto _ 上查找(即它的构造函数的prototype), 如果还没找到就会去「它构造函数的prototype的隐士原型 _ proto _ _上查找」,这样一层一层向上查找就会形成一个链式结构,我们称之为“原型链”
  • 作用
1. 数据共享,节省内存空间
2. 实现继承

5. 关于Function和Object?

  • Function是最顶层的「构造器」,构建了系统中「所有对象」
  • 「函数」也是Function构造的
 1. 函数.__proto__ === Function.prototype
  • 「Object」也是Function构造的
 2. Object.__proto__ === Function.prototype
  • 「函数本身」也是Function构造的
 3. Function.__proto__ === Function.prototype
  • Object 是最顶层的「对象」,它的_ _ proto _ _指向null
1. 所有「对象」 都继承Object的原型
函数.prototype.__proto__ ==== Object.prototype
Function.prototype.__proto__ ==== Object.prototype

2. Object也是被Function构造出来的

Function instanceof Function ===> true

Function instanceof Object ===> true

Object instanceof Object ===> true

Object instanceof Function ===> true

3. Object.prototype, 它的_ _ proto _ _指向null

Object.prototype.__proto__ === null

6. 原型、构造函数、实例?

术语: 只要是对象,它就是一个实例
术语: 任何函数都有prototype属性(js声明时自动加的)
术语: 函数都是对象, 所以他也有__propto__

1. 实例: 构造函数通过new 运算符,来生成一个实例
2. 构造函数: 任何一个函数被new, 该函数就是构造函数
3. 原型对象: 构造函数的pototype指向的对象
4. 构造器constructor: 通过它区分原型对象被哪个构造函数引用

```
1. 函数.prototype: 每个函数都有prototype
2. 对象.__proto__: 每个对象都有__proto__
3. 函数.__proto__: 每个「函数」都是「对象」
4. 函数.prototype.__proto__: 函数的prototype是对象
```

7. instanceof?

  • 概念: 判断「一个构造函数的prototype」属性所指向的对象是否在「另一个被检测对象」的原型链上

8.继承:

1. 借助构造函数实现:(部分继承)

<!--原理:改变this的指向-->
<!--父级在子级函数中执行,且修改父级构造函数的指向-->
function Parent1() {
    this.name = 'parant1'
}
function Child1() {
    Parent1.call(this);
    this.type = 'child1'
}
console.log(new Child1)

<!--缺点: Child1继承不了Parent1的原型对象上的方法-->

2. 借助原型链实现继承:

<!--原理:找属性name, Child2自己没有,找Child2.prototype, 此时Child2.prototype = new Parent2(), 可以找到name-->
function Parent2() {
    this.name = 'parant2'
}
function Child2() {
    this.type = 'child2'
}
Child2.prototype = new Parent2()
console.log(new Child2)

<!--缺点: 改一个对象属性另一个属性也被改变了,原型对象是共用的-->




3. 组合方式(构造函数 + 原型链):

function Parent3() {
    this.name = 'parant3'
}
function Child3() {
    Parent3.call(this)
    this.type = 'child3'
}

Child3.prototype = new Parent3()
<!--缺点: 父级的构造函数执行了两次-->
<!--构造函数复用-->
<!--优化后-->
Child3.prototype = Parent3.prototype
<!--缺点: 共用一个原型对象,原型对象不知道是哪个构造函数引用的-->
console.log(new Child3())


4. 组合继承的完美写法

function Parent4() {
    this.name = 'parant4'
}
function Child4() {
    Parent3.call(this)
    this.type = 'child4'
}
<!--隔离-->
Child4.prototype = Object.create(Parent4.prototype)
<!--写一个自己的constructor-->
Child4.prototype.constructor = Child4


6. class extends 继承
```
class People {
    constructor() {
        this.name = name
        
    }
    active() {
        console.log(`$this.name`)
    }
}

class Teacher extends People {
    constructor(name) {
        super(name)
        this.time = time
    }
    active() {
        console.log(`${this.name}`)
    }
}

class Doctor extends People {
    constructor(name) {
        super(name)
        this.start = start
    }
    eat() {
        console.log(`${this.name}`)
    }
}
```