🍎 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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# JavaScript 原型链
- 当访问一个对象的属性时,
- 先在自身的属性中查找,找到则返回;
- 如果没有找到,则再沿着
__proto__
这条链向上查找,找到则返回; - 如果最终没找到,则返回
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
作用:查找对象的属性(方法)
构造函数 / 原型 / 实例对象的关系 1️⃣:
var o1 = new Object() var o2 = {}
1
2构造函数 / 原型 / 实例对象的关系 2️⃣ :
function Foo(){ } // var Foo = new Function() // Function = new Function()
1
2
3注意
所有函数的
__proto__
都是一样的。
🔧 问题补充:
注意
函数的显式原型指向的对象是是空的
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
1Object
的原型对象是原型链的尽头。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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# instanceof
- 表达式:
a instanceof b
- 如果
b
函数的显示原型对象在a
对象的原型链上(则a
是b
的实例),返回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
2
3
4
🌰 例子 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
2
3
4
function Foo() { }
console.log(Object instanceof Foo) // false
1
2
2
# ⭐️ 题相关
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
2
3
4
5
6
7
8
9
10
11
12
13
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
2
3
4
5
6
7
8
9
10
11
12
13
编辑 (opens new window)
📢 上次更新: 2022/09/02, 10:18:16