理解this和原型的关键是观察调用位置与方式:调用位置决定this起点(如obj.fn()中this指向obj,f=obj.fn;f()则丢失绑定),调用方式分普通/方法/构造/显式四种;原型是委托查找链,实例通过__proto__沿prototype链向上查找属性。
理解原型和 this,关键不在死记规则,而在养成两个习惯:看函数在哪儿被调用(位置),以及看它怎么被调用(方式)。这两点一抓住,大部分迷惑就自然解开。
调用位置决定 this 的起点
所谓“调用位置”,就是函数执行时,它上一层是谁在发起调用。不是函数写在哪,而是谁在“点”它、谁在“传”它、谁在“new”它。
- 比如 obj.fn(),调用位置是 obj 这一层,this 就大概率指向 obj
- 而 const f = obj.fn; f(),调用位置已脱离 obj,变成顶层或 undefined(严格模式)
- 用 debugger 在函数第一行打断点,浏览器控制台的 Call Stack(调用栈)能直观显示这个“位置链”
调用方式决定 this 的归属
同一个函数,不同调用方式,this 指向完全不同。四种核心方式要一眼识别:
- 普通调用:如 foo() → this 是全局对象(非严格)或 undefined(严格)
- 方法调用:如 obj.method() → this 是点号前的对象(obj)
- 构造调用:如 new Foo() → this 是新创建的实例
- 显式绑定:如 fn.call(obj) 或 fn.bind(obj) → this 被强制指定为 obj
原型的本质是“委托查找链”
原型不等于模板,也不是复制副本。它是对象在访问属性或方法时,一层层向上找的路线图。
- 每个函数都有 prototype 属性(显式原型),用于给将来 new 出的实例提供共享内容
- 每个实例都有 __proto__(隐式原型),默认指向其构造函数的 prototype
- 查找规则:先查自身 → 没有就查 __proto__ → 再没有就继续向上,直到 null
this 和原型常一起出现的典型场景
很多困惑其实来自二者叠加。例如:
- 对象方法里用了箭头函数 → 箭头函数没有自己的 this,会沿作用域链向上找,跳过原型链上的调用者
- 把原型上的方法赋值给变量再调用 → 调用方式从“方法调用”退化为“普通调用”,this 失去绑定
- class 中的实例方法,默认是定义在 prototype 上的,但若未正确绑定(如事件回调),this 仍可能丢失










