我们在写前端页面的时候,编写JavaScript代码的时候经常会用到this关键字,比如绑定事件等等,但是JavaScript中的this指向问题一直都是比较让人头疼的问题,特别是对于初学者来讲,本来认为代码没有什么问题,结果运行出来不尽人意,而且还要花大量时间来调试找到问题所在。以下内容是根据自己所理解进行分享,有什么不对的地方希望大家指出,并一起讨论,一起进步。
首先我们要明白,this 是在代码执行过程中才会对其进行赋值,这也是 this 指向复杂的原因之一
在 JavaScript 中 this 默认绑定全局变量,例如在全局变量中打印 this 就会显示 window 对象
console.log(this) // window 对象 console.log(this === window) // true 这也表示在全局范围内this 默认指向 window 对象
这一点很好理解,不用多讲
总的来讲,就是谁调用就指向谁
function abc(){ console.log(this); // window } abc(); // 这里打印出的还是 window 对象,因为 abc() 等同于 window.abc(); // 还有就是当函数独立调用的时候,就是不借助其他自身调用时,this 指向的也是 window
这也很好理解,再来换一个例子
let a = 0; let obj = { a:2, fn:function(){ console.log(this); // obj function test(){ console.log(this) // ? } test(); } } obj.fn(); // 通过对象的属性的方式来调用方法时,this 就会指向对象,
但是在对象中函数中再定义一个函数时,这个时候 this 指向的会是什么呢?
回到第一点所讲过的,当函数不借助其它,通过自己来调用时,this 默认指向的是 window ,所以在上面的那个例子 第二个 this 指向的就是 window
同理,立即执行的函数中的 this 也为 window
(function(){ console.log(this) // window })()
再来看闭包中的 this
let obj = { fn:function(){ return function(){ console.log(this) } } } obj.fn()() // window
可能这里就会有疑问了,这里是用了 obj 中的属性来进行调用的,但是为什么还是输出的是 window 对象呢,因为 obj.fn() 先执行时,返回的是 test 方法的引用(也可以理解为指针),通过这个引用调用 test 方法,就等同于 test() 这又回到了第一点中的函数独立调用时,this 默认指向的是 window
再来个例子(隐式丢失)
var a = 0; function foo(){ console.log(this); } let obj = { a:2, foo:foo } obj.foo(); // 这里没有疑问,打印的 obj // 隐式丢失 let fn = obj.foo; fn(); // 这里打印出来的为 window
这个例子有一个专有名词叫做隐式丢失,我个人理解和上一个例子中的闭包中的 this 很相像,通过函数的引用来调用函数,就会丢失对象,的引用,所以叫做隐式丢失。这里还能理解为函数的独立调用,也是指向的 window。
函数传参之间的 this 指向(参数赋值)
let a = 0; function foo(){ console.log(this) // window } function bar(fn){ fn(); } let obj = { a:2, foo:foo, } bar(obj.foo)
这个例子中,通过对象中的属性来进行传递参数,最终打印出来的window对象,这里可以理解函数在传递参数的时候只是传递了函数的引用,也就是说只是传递了函数的指针,并没有传递这个函数是通过哪个对象来得到了,所以最终打印出来的也是 window 对象
通过这三个方法对函数中的 this 进行改变,在 javascript 面向对象中起着很关键的作用,知识比较多,这里就不细讲了。可以直接看 API
只有是在 构造函数时,才会用到 new 绑定。是将实例化的对象绑定到 this
function Person(){ age:18; // return 1; // return {}; } let person = new Person(); console.log(this)
这里需要注意的是返回值的问题,当返回值不是一个对象的时候,通过new来赋值的就是实例化对象本身,但是如果手动添加的返回值是一个对象,那么这个对象就会赋值给 person (实际开发过程中极少用到)