一、JavaScript 原型链
1. 基础概念
- 每个对象都有一个内部属性 [[Prototype]] ,可以通过
__proto__
或Object.getPrototypeOf(obj)
访问。 - 构造函数
Foo
有一个.prototype
属性,指向一个对象,这个对象作为实例的原型。 - 查找属性的顺序:实例 → 原型 → 原型的原型 … → Object.prototype → null
2. 典型例题示意
1function Foo() {}
2Foo.prototype.a = 1
3
4const foo = new Foo()
表达式 | 值/说明 |
---|---|
foo.a | 1 (实例自身没有,去原型链找) |
foo.__proto__ | Foo.prototype |
Foo.__proto__ | Function.prototype |
Foo.prototype.__proto__ | Object.prototype |
原型链示意图
1foo ---> Foo.prototype ---> Object.prototype ---> null
2Foo ---> Function.prototype ---> Object.prototype ---> null
3. 原型链继承问题
1function A() {}
2function B() {}
3A.prototype.x = 10
4B.prototype = new A()
5const b = new B()
6
7console.log(b.x)
8console.log(b.constructor === B)
B.prototype = new A()
后,b
的原型链:
1b ---> B.prototype (new A()) ---> A.prototype ---> Object.prototype ---> null
constructor
被覆盖,需手动修复:
1B.prototype.constructor = B
4. 函数对象 vs 实例对象原型链
1function Foo() {}
2const f = new Foo();
3
4console.log(Foo.__proto__ === Function.prototype);
5console.log(f.__proto__ === Foo.prototype);
- 函数对象链:函数本身是可调用对象 →
Function.prototype
- 实例对象链:普通对象 →
Foo.prototype
→Object.prototype
可视化图:
1函数对象 Foo: Foo ---> Function.prototype ---> Object.prototype ---> null
2实例对象 f: f ---> Foo.prototype ---> Object.prototype ---> null
记忆:函数对象和实例对象是两条独立链,方法挂在 Function.prototype 不会被实例继承。
二、this 指向
1. 基本规则
调用方式 | this 指向 |
---|---|
普通函数调用 | 全局对象(浏览器是 window,严格模式下 undefined) |
对象方法调用 | 调用者对象 |
构造函数调用(new) | 新创建的实例 |
call/apply/bind 调用 | 手动指定对象 |
箭头函数 | 定义时的词法作用域(外层 this) |
2. 典型题分析
题例:普通函数 vs arguments
1var length = 10
2function fn() { console.log(this.length)
3
4const obj = {
5 length: 5,
6 method: function(fn) {
7 fn()
8 arguments[0]()
9 }
10}
11obj.method(fn, 1)
调用 | this | 输出 |
---|---|---|
fn() | window/global | 10 |
arguments[0]() | arguments | 2 |
- 关键点:
arguments[0]()
调用者是arguments
对象,this === arguments
,而arguments.length = 2
原型链 & this 综合题
1Function.prototype.getName = function(){ return this.name; }
2function Foo() {}
3const f = new Foo();
4
5console.log(Foo.getName());
6console.log(f.getName());
Foo
是函数对象 → 可继承 Function.prototypef
是实例 → 继承自 Foo.prototype(普通对象),Function.prototype 不在其链上
3. this 指向可视化
1普通函数:
2fn()
3this ---> window/global
4
5对象方法:
6obj.method()
7this ---> obj
8
9构造函数:
10new Foo()
11this ---> 新建实例 f
12
13arguments 调用:
14arguments[0]()
15this ---> arguments
三、记忆技巧
-
原型链
- 函数对象 → Function.prototype → Object.prototype
- 实例对象 → 构造函数.prototype → Object.prototype
- 构造函数 prototype 上挂的方法 → 实例可用
-
this
- “谁调用指向谁”是最核心原则
- 箭头函数不看调用者,固定绑定外层 this
- arguments 是一个对象,调用其中的函数时 this 指向 arguments
四、总结表
概念/题型 | 关键点/技巧 |
---|---|
原型链查找属性 | 实例 → 实例.proto → … → Object.prototype |
构造函数.prototype | 实例的原型对象 |
函数对象原型链 | Foo.proto → Function.prototype → Object.prototype |
实例对象原型链 | f.proto → Foo.prototype → Object.prototype |
this 普通函数调用 | window / undefined |
this 对象方法调用 | 调用者对象 |
this 构造函数 new 调用 | 新建实例 |
this call/apply/bind | 手动指定对象 |
箭头函数 | 继承定义时的 this |
个人笔记记录 2021 ~ 2025