目录

🍎 JavaScript 原型与原型链

相关问题:

  • 说说你对原型、原型链的理解。
  • 原型有什么特点。

# JavaScript 原型

JavaScript 的每个对象都拥有一个原型对象,当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

对于函数:

  • 函数可以拥有属性,并且有一个特殊的属性为 prototype 属性:
    • 每个函数都有一个 prototype 属性,它默认指向一个 Object 空对象(即原型对象 )。
    • 原型对象中有一个属性 constructor ,它指向函数对象
  • 给原型对象添加属性(一般为方法),⭐️ 作用:函数的所有实例对象自动拥有原型中的属性(方法)。

🌰 例子:

console.log(Date.prototype, typeof Date.prototype)

function Fun(){
  
}
console.log(Fun.prototype)
console.log(Date.prototype.constructor===Date) // true
console.log(Fun.prototype.constructor===Fun) // true

Fun.prototype.test = function (){
  cosole.log("test()")
}

var fun = new Fun()
fun.test() // "test()"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

:::

# 显式原型与隐式原型

  • 显式原型:指每个函数 function 都有的原型 prototype (属性)。默认指向一个空的 Object 对象。
  • 隐式原型:指每个实例对象都有一个的 __proto__ (属性)。

对象的隐式原型的值为其对应构造函数的显性原型的值

注意

⚠️ 在 ES6 之前,程序员能直接操作显式原型但是不能直接操作隐式原型。

🌰 例子:

function Fn(){
  // ... 
} // 可理解为 this.prototype = { ... }

// (1)
console.log(Fn.prototype) // Object
// (2)
var fn = new Fn() // 可理解为 this.__proto__ = Fn.prototype
console.log(fn.__proto__) // Object
// (3)
console.log(Fn.prototype==fn.__proto__) // true

Fn.prototype.test = function () {
  console.log("test")
} // 给原型添加方法
fn.test() // test // 可以通过实例调用原型的方法 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

image-20220314231803704

# JavaScript 原型链

  • 当访问一个对象的属性时,
    1. 先在自身的属性中查找,找到则返回;
    2. 如果没有找到,则再沿着 __proto__ 这条链向上查找,找到则返回;
    3. 如果最终没找到,则返回 undefined

上述查找过程为原型链,又称为隐式原型链

🌰 例子:

function Fn(){
  this.test1 = function (){
    console.log("test1)")
  }
}

Fn.prototype.test2 = function () {
  console.log("test2()")
}

var fn = new Fn()

fn.test1()
fn.test2()
console.log(fn.toString())
fn.test3() // ERROR!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

image-20220314233659423

作用:查找对象的属性(方法)

  • 构造函数 / 原型 / 实例对象的关系 1️⃣:

    var o1 = new Object()
    var o2 = {}
    
    1
    2

    image-20220315230351898

  • 构造函数 / 原型 / 实例对象的关系 2️⃣ :

    function Foo(){ }
    // var Foo = new Function()
    // Function = new Function()
    
    1
    2
    3

    注意

    所有函数的 __proto__ 都是一样的。

    image-20220317110231668

🔧 问题补充

注意

  • 函数的显式原型指向的对象是是空的 Object 实例对象,但是 Object 不满足。

    console.log(Fn.prototype instanceof Object) // true
    console.log(Object.prototype instanceof Object) // false
    cosole.log(Function.prototype instanceof Object) // true
    
    1
    2
    3
  • 所有的函数都是 Function实例,包括 Function 本身( Function 是它自身的实例)。

    console.log(Function.__proto__===Function.prototype) // true
    
    1
  • Object 的原型对象是原型链的尽头

    console.log(Object.prototype.__proto__) // null
    
    1

# 原型链的属性问题

  • 读取对象的属性时,会自动到原型链中查找
  • 设置对象的属性值时,⚠️ 不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置此值。
  • 方法一般定义在原型中,属性一般通过构造函数定义在对象本身上。

🌰 例子:

function Fn() {}
Fn.prototype.a = 'xxx'
var fn1 = new Fn()
console.log(fn.a) // 'xxx'

var fn2 = new Fn()
fn2.a = 'yyy'
console.log(fn1.a) // 'xxx'
console.log(fn2.a) // 'yyy' 
//  cosole.log(fn2.__proto__.a) // 'xxx'
1
2
3
4
5
6
7
8
9
10

🌰 例子:

function Person(name, age) {
  this.name = name
  this.age =age
}

Person.prototype.setName = function(name) = {
  this.name = name
}

var p1 = new Person('Tom', 12)
p1.setName('Bob')
console.log(p1.name, p1.age) // Bob, 12

var p2 = Person('Sid', 12)
p2.setName('Kat')
console.log(p2.name, p2.age) // Kat, 12
console.log(p1.__proto__==p2.__proto__) // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# instanceof

  • 表达式: a instanceof b
  • 如果 b 函数的显示原型对象a 对象的原型链上(则 ab 的实例),返回 true ,否则返回 false

🌰 例子 1️⃣ :

function Foo() { }
var f1 = new Foo() // 左边实例对象,右边构造函数
console.log(f1 instanceof Foo) // true
console.log(f1 instanceof Object) //* true 
1
2
3
4

image-20220317141149124

🌰 例子 2️⃣:

console.log(Object instanceof Function) // true
console.log(Object instanceof Object) // true
console.log(Function instanceof Function) // true
console.log(Function instanceof Object) // true
1
2
3
4
function Foo() { }
console.log(Object instanceof Foo) // false
1
2

image-20220317143213847

# ⭐️ 题相关

1️⃣

function A() { }
A.prototype.n = 1

var b = new A()

A.prototype = {
  n: 2,
  m: 3
}

var c = new A()

console.log(b.n, b.m, c.n, c.m) // 1 undefined 2 3 
1
2
3
4
5
6
7
8
9
10
11
12
13

image-20220317145444983

2️⃣

function F() { }
Object.prototype.a = function(){
  console.log('a()')
}
Function.prototype.b = function(){
  console.log('b()')
}

var f = new F()
f.a() // 'a()'
// f.b() // error
F.a() // 'a()'
F.b() // 'b()'
1
2
3
4
5
6
7
8
9
10
11
12
13
📢 上次更新: 2022/09/02, 10:18:16