目录
this 是什么?
箭头函数中的 this
为什么要改变 this 指向?
改变 this 指向的三种方法
call(无数个参数)
apply(两个参数)
bind(无数个参数)
this 是什么?
- 在对象方法中,this 指的是所有者对象(方法的拥有者)。
var person = {firstName: "Jasmine",lastName: "Ge",id: 10108888,fullName: function(){return this.firstName + " " + this.lastName;} }; console.log(person.fullName()) // Jasmine Ge
- 单独的情况下,this 指的是全局对象。
// 在浏览器窗口中 this // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
- 在函数中,this 指的是全局对象。
(function myFunction(){return this; })() // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
- 在函数中,严格模式下,this 指的是 undefined。
// js 严格模式不允许默认绑定,因此,在函数中使用时,在严格模式下,this 是未定义的undefined "use strict"; (function myFunction(){return this; })() //undefined
- 在事件中,this 指的是接收事件的元素。
<button onclick = "this.style.backgroundColor='skyblue'; console.log(this)">点击来帮我改变颜色! </button>
箭头函数中的 this
箭头函数中的 this 等同于上一层非箭头的函数的 this 值或全局对象(window 或 undefined)
解释: 在箭头函数中,this 的指向是由外层(函数或者全局)作用域来决定,如果往外层作用域查找 this 的指向,只要没有非箭头函数(普通函数)的包裹,就一直往外层查找,直到最外层的全局作用域。如果没有非箭头函数(普通函数)的包裹,即使包裹再多层对象 this 也是指向全局作用域的。
let name = 'obj'
let obj1 = {name: 'obj1',obj2: {name: 'obj2',obj3: {name: 'obj3',obj4: {name: 'obj4',fn: () => {console.log(this) // node环境中输出 {},浏览器中输出 window}}}}
}obj1.obj2.obj3.obj4.fn()
// Window {0: Window, 1: Window, window: Window, self: Window, document: document, name: 'obj', location: Location, …}
为什么要改变 this 指向?
项目中有如下类似例子,find 函数中的 this 指向调用它的 obj 对象;而在定时器 setTimeout 中调用 find(),this 是指向 window 对象的。但我们需要 find 函数中 的 this 指向 obj 对象,因此我们需要修改 this 的指向。
var position = "这是 windows 的 position";
let obj = {position: "这是 obj 的 position",find: function() {console.log(this.position)}
};
obj.find(); // 这是 obj 的 position,this指向obj对象
setTimeout(obj.find, 0); // 这是 windows 的 position,由于 setTimeout() 是异步操作,this 指向 window 对象
改变 this 指向的三种方法
共同点:第一个参数都为改变 this 的指针。若第一参数为 null / undefined,this 默认指向 window
call(无数个参数)
- 没有参数的时候,指向window
- 有一个参数的时候,指向当前参数
- 有多个参数,this指向第一个参数,剩下的参数是参数列表
function fn(a, b, c){console.log(this, a + b + c); // this指向window
}
fn();
// Window {0: Window, 1: Window, 2: Window, 3: Window, window: Window, self: Window, document: document, name: '', location: Location, …} NaN
fn.call(document, 1, 2, 3); // call 之后 this 指向 document
//输出 #document 6 1,2,3是实参 结果相加为6
apply(两个参数)
- 没有参数的时候,指向window
- 有一个参数的时候,指向当前参数
- 有多个参数,this指向第一个参数,剩下的参数是数组
function fn(a, b, c){console.log(this, a+b+c);
}
fn();
// Window {0: Window, 1: Window, 2: Window, 3: Window, window: Window, self: Window, document: document, name: '', location: Location, …} NaN
fn.apply(document, [1, 2, 3]); // apply之后 this 指向 document
// #document 6
bind(无数个参数)
- 没有参数的时候,指向 window
- 有一个参数的时候,指向当前参数
- 返回值为一个新的函数
- 使用的时候需要手动调用下返回 的新函数(不会自动执行)
function fn(a, b, c){console.log(this, a+b+c);
}
fn()
// Window {0: Window, 1: Window, 2: Window, 3: Window, window: Window, self: Window, document: document, name: '', location: Location, …} NaN
let ff = fn.bind('小明', 1, 2, 3);
// 手动调用一下
ff()
// String {'小明'} 6