导航
window、self、frames、this
global、globalThis
self
globalThis
var a = 1;
var b = function() { console.log('fun b中的this:', this) }
c = {};
console.log('this === window', this === window);
console.log('window.a === a:', window.a === a);
b();
console.log('window.c === this.c:', window.c === this.c);
严格模式下:
"use strict";
c = 123;
"use strict";
var b = function() { console.log('fun b中的this:', this) }
b();
function test() {
"use strict";
return this;
}
window.test(); // window
// 谁调用函数,函数内部的this指向谁
global.a
a
(不通过 var、let、const 声明都都在全局,用这三个声明的变量会挂载到当前模块中而不是全局)var a = 1;
b = function() { console.log(this) };
global.c = 2;
console.log(a);
console.log(b);
console.log(c);
console.log(global.a);
console.log(global.b);
console.log(global.c);
b();
"use strict";
var b = function() { console.log(this) };
b(); // undefined
class Father {
constructor(age) {
this.age = age;
}
swim() {
console.log('Go swimming!!!');
}
}
class Son extends Father {
constructor() {
super(23);
this.hobby = 'travel';
console.log(this.age);
}
study() {
console.log(this);
this.swim();
}
}
const son = new Son();
son.study();
不能调换 super 顺序,得首先调用 super:
class Son extends Father {
constructor() {
this.hobby = 'travel';
super(23);
}
}
原因是按照正常顺序:
而如果先执行子类 constructor 中代码,后执行 super,就会导致先实例化了子类 this,再实例化父类 this,这样逻辑就不对了。
class Father {
get fruit() {
return 'apple';
}
eat() {
console.log('I am eating an ' + this.fruit);
}
}
class Son {
get fruit() {
return 'orange';
}
}
const father = new Father();
const son = new Son();
father.eat(); // apple
son.eat = father.eat;
son.eat(); // orange
如果希望son调用eat时,还是拿的 father 中的 apple,可以在constructor中bind固定this:
class Father {
constructor() {
// 让函数内部的this指向固定
// 这样无论再把eat赋给谁,this都不会改变了
this.eat = this.eat.bind(this);
}
get fruit() {
return 'apple';
}
eat() {
console.log('I am eating an ' + this.fruit);
}
}
class Son {
get fruit() {
return 'orange';
}
}
const father = new Father();
const son = new Son();
father.eat(); // apple
son.eat = father.eat;
son.eat(); // apple
var obj = {
a: 1
}
var a = 2;
function test(b, c) {
console.log(this);
}
test();
test.call(obj, 3, 4);
test.apply(obj, [3, 4]);
var obj = {
a: 1
}
var obj2 = {
a: 100
}
function test(b, c) {
console.log(this, b, c);
}
var test1 = test.bind(obj, 3, 4);
test1();
var test2 = test1.bind(obj2, 3, 4);
test2();
var obj = {
a: 1
}
var obj2 = {
a: 100
}
function test(b, c) {
console.log(this, b, c);
}
var test1 = test.bind(obj2, 3, 4).bind(obj, 3, 4);
test1();
不管是否是严格模式,全局下箭头函数的this都为window
const test = () => {
console.log(this);
}
test(); // window
"use strict";
const test = () => {
console.log(this);
}
test(); // window
箭头函数忽略任何形式的this指向的改变(apply,call,bind):
var obj = {
a: 1
}
const test = () => {
console.log(this.a);
}
test.call(obj); // undefined
test.apply(obj); // undefined
var test1 = test.bind(obj);
test1(); // undefined
箭头函数中 this 不是在执行期确定,而是声明时就已确定,而且无法更改:
var obj = {
a: 1
}
obj.test = () => {
console.log(this);
}
obj.test(); // window
var obj = {
a: 1
}
obj.test = function() {
var t = () => {
console.log(this); // obj
}
t();
}
obj.test();
var obj = {
a: 1
}
obj.test = function() {
var t1 = () => {
var t2 = () => {
console.log(this); // obj
}
t2();
}
t1();
}
obj.test();
var obj = {
a: 1
}
obj.test = function() {
var t1 = function() {
var t2 = () => {
console.log(this);
}
t2();
}
t1();
}
obj.test();
var obj = {
a: 1,
b: 2,
test: function() {
console.log(this.a); // 1
},
test2: test2,
c: {
d: 4,
test3: function() {
console.log(this);
console.log(this.d);
}
}
}
function test2() {
console.log(this.b);
}
obj.test();
obj.test2();
obj.c.test3();
var obj2 = {
a: 1,
b: 2,
test3: function() {
function t() {
// 这个函数t是孤立的,不是 obj2 内部的成员
// 并不存在 obj2.t, t()自调用,默认this为window
console.log(this);
}
t(); // window
}
}
obj2.test3();
var a = 8;
var o = {
a: 10,
b: {
fn: function() {
console.log(this.a);
}
}
}
o.b.fn(); // undefined
var obj = {}
obj.__proto__ = {
e: 20
}
console.log(obj.e); // 20 原型继承
var obj = Object.create({
test4: function() {
console.log(this.a + this.b);
}
});
obj.a = 1;
obj.b = 2;
obj.test4(); // 3
function Test() {
this.a = 1;
this.b = 2;
console.log(this); // {a:1,b:2}
return {
c: 3,
d: 4
}
}
var test1 = new Test();
console.log(test1); // {c:3,d:4}
onclick
、addEventListener
事件处理函数内部的 this 总是指向被绑定的 DOM 元素<body>
<button id="btn">点我</button>
</body>
var btn = document.getElementById('btn');
btn.onclick = function() {
console.log(this); // btn元素
}
btn.addEventListener('click', function() {
console.log(this); // btn元素
}, false);
直接在元素上绑定,this 还是 btn: