全局环境 this
在全局执行环境中,
this
都指向浏览器的window
console.log(this === window); // true
this.name = 'window的name';
console.log(window.name); // window的name
普通函数 this
普通函数被直接调用时,
this
都指向浏览器的window
,不限嵌套层数
function outFn() {
console.log('outFn', this, this === window);
function innerFn() {
console.log('innerFn', this, this === window);
}
innerFn();
}
outFn();
// 打印结果:
// outFn window {……} true
// innerFn window {……} true
构造函数 this
在构造函数内部环境中,
this
都指向实例对象
function Fn(name) {
this.name = name;
this.getName = function () {
console.log(`实例对象${this.name}:`, this);
}
}
const obj = new Fn('obj');
const arr = new Fn('arr');
obj.getName();
arr.getName();
// 打印结果:
// 实例对象obj: Fn {name:'obj', ……}
// 实例对象arr: Fn {name:'arr', ……}
对象属性 this
当函数为一个对象的属性时,
this
指向调用该函数的 最近对象。
const obj = {
name: 'obj',
getName: function () {
console.log('this:', this);
console.log('this指向obj?', this === obj);
}
}
obj.getName();
// 打印结果:
// this: {name: 'obj', getName: f}
// this指向obj? true
// 为obj对象增加一个子属性child
obj.child = {
childName: 'obj.child',
getChildName: function () {
console.log('this:', this);
console.log('this指向obj?', this === obj);
console.log('this指向obj.child?', this === obj.child);
}
};
obj.child.getChildName();
// 打印结果:
// this: {childName: 'obj.child'', getChildName : f}
// this指向obj? false
// this指向obj.child? true
事件绑定 this
通过js进行事件绑定的函数,
this
指向触发事件的dom元素
<button id='btn'>按钮</button>
function Fn(e) {
console.log('this:', this);
console.log('this === e.currentTarget', this === e.currentTarget);
}
const btn = document.getElementById('btn'); // 假设有一个button按钮,id为btn
btn.addEventListener('click', Fn, false); // 绑定click事件
// 点击button后,打印结果:
// this:<button id='btn'>按钮</button>
// this === e.currentTarget true
作为一个内联事件时,当在函数外层的
this
时,指向触发事件的dom元素,当在函数内部时,则跟普通函数一样,指向window
<!-- 函数外层 -->
<button onclick='console.log("按钮1",this)'>按钮1</button>
<!-- 函数内部 -->
<button onclick="fn()">按钮2</button>
<!-- 函数内部 -->
<button onclick='(function(){console.log("按钮3",this)})()'>按钮3</button>
function fn() {
console.log('按钮2:', this);
}
// 分别点击按钮1、2后,打印结果:
// 按钮1 <button οnclick='console.log("按钮1",this)'>按钮1</button>
// 按钮2 window {……}
// 按钮3 window {……}
Class类 this
Class类中的
this
指向实例对象,而静态函数中的this
则指向class
本身。
class Person {
constructor(name, old) {
this.name = name;
this.old = old;
console.log(`${this.name}的年龄是${this.old}`);
}
getThis() {
return this;
}
}
const Lee = new Person('李', 20);
const Su = new Person('苏', 18);
console.log('Lee的this:', Lee.getThis());
console.log('Su的this:', Su.getThis());
// 打印结果:
// 李的年龄是20
// 苏的年龄是18
// Lee的this: Person {name:'李', old: 20, __proto__: Object}
// Su的this: Person {name:'苏', old: 18, __proto__: Object}
细心的童鞋估计发现了一个现象,为什么打印出来this
的值,没有constructor
和getThis
的函数的?点开__proto__
后如下:
// Su的this值:
{
name: '苏',
old: 18,
__proto__: {
constructor: class Person,
getThis: f getThis(),
__proto: Object
}
}
有些了解过原型链的童鞋估计觉得上面很眼熟了。
由于class
类,也是基于原型和原型链做的,所以简单的class
也可以等于:
function Person(name, old){
this.name = name;
this.old = old;
}
Person.prototype.getThis = function () {
return this;
}
const Su = new Person('苏', 18);
console.log('Su:', Su); // 打印结果可以尝试一下看看,跟上面的是一样的。
不过
class
也有一点不同的,就是class
存在静态函数。函数内的this
指向的是class
本身。
class Person{
static getThis(){
return this;
}
}
console.log('class静态函数的this:',Person.getThis());
// 打印结果:
// class Person……
PS:
关于原型链可以参考:《javascript 原型和原型链》
关于如何改变this
指向可以参考:《javascript 关于bind、apply、call函数改变this指向》