# this
# 默认绑定
# 全局模式下this指向window(web 环境)
// 获取全局对象,this默认为:
// web: window,self,frames
// node: global(必须显示定义global.a=1)
// worker: self
// 通用: globalThis
function foo() {
console.log(this.a);
}
var a = 2;
foo(); // 2
# 严格模式,全局对象无法使用默认绑定
调用的时候使用window.foo()才可以正常输出
function foo() {
"use strict";
console.log(this.a);
}
var a = 2;
foo(); // TypeError: this is undefined
window.foo(); // 2。 谁调用,输出谁
// 函数内的全局this指向undefined,函数外的全局this指向window
# 对象方法内部的 this->最近的引用
谁调用指向谁
obj.a.b.c() -> obj.a.b
var obj = {
a: 1,
test: function () {
// this指向obj
console.log(this.a);
},
};
obj.test(); // 1
# 绑定事件
# 绑定的事件处理函数内部的 this 指向被绑定的元素
var oBtn = document.getElementById("btn");
oBtn.onclick = function () {
console.log(this); // this指向oBtn
};
oBtn.addEventListener("click", this.fn);
function fn() {
console.log(this); // 指向oBtn,如果需要改变,可以通过bind,oBtn.addEventListener("click", this.fn.bind(this));
}
# Object.defineProperty
当使用函数Object.defineProperty来定义的时候,具体的 this 还是根据定义的get函数来判断
var o = {};
Object.defineProperty(o, "a", {
get() {
console.log(this);
},
});
o.a; // o = {}
var o = {};
Object.defineProperty(o, "a", {
get: () => {
console.log(this);
},
});
o.a; // window
# 显示绑定
call/apply/bind
ps: bind 只会执行第一次,之后调用无效 ps: call/apply/bind 的一个参数为空或者 null,undefined,会自动将 this 绑定成全局对象
# new 绑定
- 创建(或者说构造)一个全新的对象。
- 这个新对象会被执行[[原型]]连接。
- 这个新对象会绑定到函数调用的 this。
- 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
function fn() {
this.a = 1;
this.b = 1;
return {
c: 1,
};
}
var f = new fn();
console.log(f); // {c:1}
如果显示的返回对象,则this指向的新对象会被忽略。
在 class 内定义的 a 方法相当于原型上的方法,this.a=1相当于在实例对象定义了a, 在作用域链中优先级高于原型。
class Test {
constructor() {
this.a = 1;
}
a() {}
}
const t = new Test();
console.log(t.a); // 1
# 优先级
- 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。 var bar = new foo()
- 函数是否通过 call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是 指定的对象。 var bar = foo.call(obj2)
- 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上 下文对象。 var bar = obj1.foo()
- 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到 全局对象。 var bar = foo()
# bind 模拟
/*
* 思路:
* 1.通过用法可知,输入一个函数f,调用bind方法,bind方法为f的构造函数Function的prototype绑定,返回一个函数
* 2.原函数和新函数都可以传参数
* 3.作为构造函数new的时候,bind指定的this会失效(指向实例后的对象),参数却存在
* 4.原函数的prototype内的方法可以给新函数的实例用
* 5.防止直接修改新函数的prototype来影响旧函数,可以通过空函数中转
*/
# 箭头函数
this 根据外层函数或者全局的作用域来决定,是一种继承,并且无法被修改(call/apply/bind 等),也无法被 new
通过 babel 可以知:
const a = () => {
console.log(this);
};
// 等价于
var _this = this;
var a = function a() {
console.log(_this);
};
原型 →