JS当中的函数中的this指向问题
函数中的this指向
到es6,javascript中新增了箭头函数。而对于函数的this指向问题,我自己的理解就是对于普通函数来说,什么时候调用普通函数,普通函数当中的this指向才能确认;而对于箭头函数来说,当箭头函数被声明的时候,其函数体内部使用到的this的指向就已经确定了。
普通函数
函数声明的方式:
function test () {};
匿名函数表达式:
const test = function () {};
命名函数表达式:
const test = function testName () {};
普通函数的this指向
对于普通函数来说,它内部的this是在该函数执行的时候确认的(你也可以理解为被谁调用)。
普通函数没有被显示修改其this指向(包括apply或者对象调用等),那普通函数内部的this在非严格模式下是指向windows,在严格模式下指向undefined。
普通函数直接执行
普通函数内部的this指向Global(windows是在浏览器环境下的,windows对Global实现了代理)
function test1 () {
console.log(this)
}
只要普通函数没有通过bind,apply,call或者对象调用等强制修改函数的this指向,那普通函数执行时内部的this在浏览器环境当中就指向windows,无论是在哪个作用域当中(非严格模式下)。
let obj = {name: 'lxh'};
function test () {
function fn () {
console.log('我的this', this);
}
fn();
}
test.call(obj);
对于命名函数表达式与匿名函数表示来说也是一样的
let obj = {name: 'lxh'};
function test () {
const fn = function () {
console.log('匿名函数表达式this', this);
}
fn();
const fn2 = function fnName () {
console.log('命名函数表达式的this', this);
}
fn2();
}
test.call(obj);
普通函数被显示修改this指向
通过call、apply或者bind这种来强制修改普通函数当中的this的指向
//通过call、apply或者bind这种来强制修改普通函数当中的this的指向
let obj1 = {
age: 11,
}
const test = function () {
console.log('我被修改this指向了', this);
}
test.call(obj1);
作为对象属性被调用
//或者作为对象属性被调用
const test = function () {
console.log('我被修改this指向了', this);
}
let obj2 = {
test: test,
}
obj2.test()
像一些经常使用到的api其内部都是修改了你函数的this指向了(想到了回来更新)
- addEventListener(callback) => 将你传入的callback函数的this指向修改为了对应的DOM元素
箭头函数
对于箭头函数内部的this指向来说,在箭头函数被定义的时候就已经确定了。我自己的理解就是箭头函数内部的this会指向最近的作用域当中的this。
全局作用域下
const test = () => {
console.log('箭头函数的this指向', this);
}
test();
看到这里你可能好奇为啥普通函数指向的this指向global,但是箭头函数的this指向了一个空对象
全局下的箭头函数与普通函数为什么内部调用的this不一样呢
对于普通函数来说,其实你在函数体内调用的this是函数的一个属性,就和arguments一样,这个this保存着一个指向,对于普通函数直接执行来说,函数的this属性会保存windows或undefined。但对于箭头函数来说函数对象当中没有this这个属性,所以会沿着作用域链去寻找这个this,而全局中的this不一定指向windows。这也就是为什么普通函数能够通过bind或者对象调用来改变this的指向,但箭头函数没作用。
let obj = {
name: 'lxh'
}
function fn1 () {
console.log('fn1函数的this指向', this);
const fn2 = function fn2Name () {
console.log('fn2函数的this指向', this);
const fn3 = () => {
console.log('箭头函数的this指向是什么', this);
}
fn3()
}
fn2()
}
fn1.call(obj);
重点看一下打印的结果是不是与上面的解释重合
这也说明了箭头函数的this内部使用的this是在声明的时候就确认了,因为作用域链已经确定了
总结
普通函数有一个this属性,这个this属性保存着一个引用,当函数内部使用this的时候,会读取这个this。
箭头函数没有this属性,所以在箭头函数内部使用this的时候其实是沿着作用域链去寻找这个this的。
这也同样解释了普通函数为什么可以通过bind或者对象等方式来修改this指向,而箭头函数不可以。前者是一个自有属性,被修改的话内部调用this也会反应出变化;但是后者没有this属性,箭头函数是通过作用域链去寻找这个this的,这也就是为什么箭头函数的this与最近的作用域当中的this是同一个!
个人理解,如有错误请批评指正。谢谢!