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