this指向调用函数的对象。
this一定指向一个对象。
this的指向一定是一个对象(面向对象:函数一定是被某个对象调用)。
1、全局作用域下,this始终指向window对象。
console.log(this);//window
2、函数内部的this,在非严格模式下,指向window对象:
aa()
function aa() {
bb();
console.log(this);//window
function bb() {
console.log(this);//window
}
}
3、函数内部的this,在严格模式下:
aa();
window.aa();
function aa() {
'use strict'
console.log(this);
}
使用aa()调用时,this是undefined,使用window.aa()调用时,指向window。
4、对象中的this,谁调用就指向谁:
const obj = {
fn: function () {
console.log(this)
},
abc: {
fn: function () {
console.log(this)
}
}
}
obj.fn();//obj
obj.abc.fn();//obj.abc
如果对象b继承对象a:
const a = {
fn:function(){
console.log(this)
}
}
const b = Object.create(a);
b.fn();//this指向b
a.fn();//this指向a
5、箭头函数中的this:
箭头函数中没有this和arguments。 箭头函数的this指向window
const obj = {
abc: {
fn: () => {
console.log(this)
}
}
}
obj.abc.fn();
//因为obj在window作用域下,所以箭头函数的this指向window。
6、构造函数中的this:
构造函数在生成对象时,this指向生成的对象实例。没有生成前,函数的this没有确定指向。
function fn() {
this.a = 123;
this.b = function () {
console.log(this);
}
}
let abc = new fn();
abc.b();
7、原型链中的this:
指向它调用它的对象,而不是从原型链上找到它时,它所属于的对象。
const father = {
a: function () {
console.log(this)
}
}
const son = { b: 2 };
Object.setPrototypeOf(son, father)
father.a()//father
son.a()//son
call、apply、bind可以改变this的指向。
const obj = { a: 1 };
fn(1, 2, 3, 4, 5);
fn.call(obj, 1, 2, 3, 4, 5);
function fn(a, b, c, d, e) {
console.log(this, a, b, c, d, e);
}
const obj = { a: 1 };
fn(1, 2, 3, 4, 5);
fn.apply(obj, [1, 2, 3, 4, 5]);
function fn(a, b, c, d, e) {
console.log(this, a, b, c, d, e);
}
call要求调用函数时的参数,以传统的方式附加。
apply要求调用函数时的参数,必须以数组的形式传入。
const obj = { a: 1 };
fn(1, 2, 3, 4, 5);
const f = fn.bind(obj);
f(1, 2, 3, 4, 5)
function fn(a, b, c, d, e) {
console.log(this, a, b, c, d, e);
}
bind方法不会直接调用函数,而是返回一个this指向确定的新函数。
总结:
-
call 、apply、bind都会改变函数执行时 this的指向。
-
call、apply是直接执行函数,而 bind是不执行函数,返回新的函数。
-
call要求其他参数正常传入,apply要求其他参数以数组的形式统一传入。
const h1 = document.querySelector('h1');
const h2 = document.querySelector('h2');
h1.onclick = h1_click.bind(h2);
function h1_click() {
this.style.color = 'red';
}
某些情况下,我们可能会书写一个函数,用来为一系列元素进行操作,但是,开始又不确定是对哪个元素操作,就可以使用this替代。
在调用时,有bind确定this的指向。
const h1 = document.querySelector('h1');
const h2 = document.querySelector('h2');
h1.onclick = h1_click;
const h2_hide = hide.bind(h2);
const h1_hide = hide.bind(h1);
function h1_click() {
h2_hide();
h1_hide();
}
function hide() {
const elem = this;
let o = 1;
aa();
function aa() {
if (o > 0) {
o -= 0.01;
elem.style.opacity = o;
setTimeout(aa, 10);
// requestAnimationFrame(aa);
}
}
}
在这里,我们设置了hide函数,但执行的主体不确定,因此用this替代。
const h2_hide = hide.bind(h2);
const h1_hide = hide.bind(h1);
将hide函数不确定的this,指向确定的对象,返回新的函数。