开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
前言
this
指向是一个非常重要的知识点,可以用在构造函数
,表示实例对象
;也可以用在其他场合。
this
总是返回一个对象
。
this 指向
之前的文章执行上下文
中介绍过:在创建执行上下文(即调用函数)这个阶段,除了会确定变量对象(VO
)、作用域以外,还会确定 this
指向,也就是说函数体内的this
指向跟函数在哪定义无关,跟如何调用函数有关
this
的指向规律可以总结为下面几点:
直接调用函数,在严格模式下,函数内的 this
会指向 undefined
,在非严格模式下则会绑定到全局对象上(window
或者global
,取决于代码运行环境)
function f1() {
console.log(this); // 全局对象 window/global
}
function f2() {
'use strict' // 开启严格模式
console.log(this); // undefined
}
f1();
f2();
通过对象调用,this
指向调用的对象
const foo = {
bar: 10,
fn: function() {
console.log(this);
console.log(this.bar);
}
}
// 通过 obj.function 的方式调用,this 会指向 obj
// 此处 this 指向 foo 对象,输出结果为:{ bar: 10, fn: function(){} }, 10
foo.fn();
let fn1 = foo.fn;
// 直接调用。上面赋值语句是将foo.fn的引用赋值给fn1
// 此处 this 指向全局对象 输出结果为:window/global undefined
fn1();
通过 new 关键字调用构造函数时,this 指向新创建的实例对象
function Person(name) {
this.name = name;
}
Person.prototype.say = function() {
console.log(this);
console.log('hello ' + this.name);
}
const p = new Person('world');
// this 指向 实例对象 p
p.say(); // Person {name: 'world'} hello world
this 指向绑定事件的元素
DOM
元素绑定事件时,事件处理函数里面的 this
指向绑定了事件的元素。
和 target
属性有所区别,target
指向的是触发事件的元素。
<ul id="color-list-wrap">
<li>red</li>
<li>yellow</li>
<li>blue</li>
<li>green</li>
<li>black</li>
<li>white</li>
</ul>
let colorList = document.getElementById("color-list");
colorList.addEventListener("click", function (event) {
console.log('this:', this); // 指向 ul 元素
// 事件函数内部定义 callback 函数
const callback = function() {
// 直接调用函数, this 指向 全局对象 window
console.log(this); // window
}
callback();
})
箭头函数的 this 默认使用的是外层函数的 this
const foo = {
bar: 10,
fn1: function() {
console.log(this);
console.log(this.bar);
},
fn2: () => {
console.log(this);
console.log(this.bar);
},
}
// 普通函数
foo.fn1();
// 通过对象调用,普通函数的this会指向对象,但箭头函数的this使用的是外层函数的this
// 此处 箭头函数内的this指向全局对象
// 输出结果:window/global undefined
foo.fn2();
小结
- 严格模式下,全局的
this
指向undefined
;非严格模式下,全局的this
指向 全局对象(window/global
,取决于运行环境) - 函数体内的
this
指向与函数在哪定义无关,取决于如何调用函数 - 箭头函数本身无
this
,默认使用的是定义时的外层函数的this
改变 this 指向
除了调用函数和箭头函数会隐式的决定*this
指向外,也可以通过以下三个方法手动确定this
的指向*
call 方法修改 this 指向
call
方法可以指定 this
的指向,然后在指定的作用域中指向函数。
语法:
function.call(thisArg, arg1, arg2, ...)
thisArg
:可选的。在 function
函数运行时使用的 this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null
或 undefined
时会自动替换为指向全局对象,原始值会转换为包装类型
。
arg1, arg2, ...
:可选值。参数列表,会传递给 function
apply 方法修改 this 指向
apply 方法与 call 方法作用完全相同,只是语法上有细微的区别:要传递给原函数的参数是一个数组,而不是多个参数。
语法:
function.call(thisArg, argsArray)
bind 方法修改 this 指向
bind
方法与 call
在语法上相同,但是 bind
方法会返回一个新函数,该函数的 this
指向 bind
方法的第一个参数
语法:
function.bind(thisArg[, arg1[, arg2[, ...]]])
小结
关于 call
、apply
、*bind
*的详细介绍及手写实现见文章 --- call、apply、bind的实际应用及实现原理